C++ 当数字变小时,long是否会将其四舍五入?
我使用的是Manjaro 64位最新版本。HP pavilion g6,代码块 发布13.12版本9501(2013-12-25 18:25:45)gcc 5.2.0 Linux/unicode-64位 学生们讨论了原因C++ 当数字变小时,long是否会将其四舍五入?,c++,gcc,C++,Gcc,我使用的是Manjaro 64位最新版本。HP pavilion g6,代码块 发布13.12版本9501(2013-12-25 18:25:45)gcc 5.2.0 Linux/unicode-64位 学生们讨论了原因 sn=1/n发散 sn=1/n^2收敛 所以决定写一个关于它的程序,只是为了向他们展示他们能期望得到什么样的输出 #include <iostream> #include <math.h> #include <fstream> usin
- sn=1/n发散
- sn=1/n^2收敛
#include <iostream>
#include <math.h>
#include <fstream>
using namespace std;
int main()
{
long double sn =0, sn2=0; // sn2 is 1/n^2
ofstream myfile;
myfile.open("/home/Projects/c++/test/test.csv");
for (double n =2; n<100000000;n++){
sn += 1/n;
sn2 += 1/pow(n,2);
myfile << "For n = " << n << " Sn = " << sn << " and Sn2 = " << sn2 << endl;
}
myfile.close();
return 0;
}
#包括
#包括
#包括
使用名称空间std;
int main()
{
长双sn=0,sn2=0;//sn2是1/n^2
流文件;
myfile.open(“/home/Projects/c++/test/test.csv”);
对于(double n=2;n来说,您编写的代码有一个典型的编程错误:它首先将较大的数字相加,然后再将较小的数字相加,从而对浮点数序列求和
这将不可避免地导致加法过程中的精度损失,因为在序列的某个点上,和将变得相对较大,而序列的下一个成员将变得相对较小。将足够小的浮点值添加到足够大的浮点和中不会影响和。一旦达到该点,即使尝试添加的值不是零,加法操作看起来也会被“忽略”
如果在典型机器上尝试计算100000000.0f+1
,您可以观察到同样的效果:它的计算结果仍然是100000000
。这不会发生,因为1
以某种方式被舍入为零。这是因为数学上正确的结果10000001
被舍入回100000000
。为了通过添加强制更改100000000.0f
,您需要至少添加5
(并且结果将“捕捉”到10000008
)
因此,这里的问题并不是编译器“在它变得如此小时对数字进行舍入”,正如您似乎相信的那样。您的1/pow(n,2)
数字可能很好并且足够精确(没有舍入到0)。这里的问题是在循环的某个迭代中,1/pow(n,2)的小非零值
再也不能影响总和了
虽然调整输出精度确实会帮助您更好地了解正在发生的事情(如评论中所述),但真正的问题是上述内容
在计算成员大小差异较大的浮点序列的和时,应首先添加较小的序列成员。再次使用我的100000000.0f
示例,您可以很容易地看到4.0f+4.0f+100000000.0f
正确地生成10000008
,而100000000.0f+4.0f+4.0f
仍然是100000000
这里没有遇到精度问题。总和不会停在0.644834;:
注意9!这不再是0.644834了
<>如果您预期1.644934,则应该在n=1 < /Cord>中开始求和。如果您预期连续的部分和之间出现可见的变化,则没有看到那些,因为C++将总和的表示截断为6个有效数字。可以配置输出流以显示更多的数字,并使用<代码> STD::StestPrimsion
来自iomanip
标题:
myfile << std::setprecision(9);
<代码> MyFipe,这都是输出数字的原因。@ DavidSchwartz不适合在线。没有意义,如果第一行不适合,C++不能写在下一行上吗?输出的默认精度是6位数。如果你想看到其余的,你必须多问一些,例如:代码> cou@ bPopssAHHHHHOMSEME,我能要求它超额吗?但直到数字的末尾,不管它可能有多长?只是一个旁注:如果你真的想理解为什么一个收敛而另一个不收敛,你应该做一些数学计算。收敛/发散的定义不能用一个运行有限时间的程序来证明。这实际上不是问题。com有足够多的精度可用用简单的方法把这个总数设为6位数。OP可能只是等待的时间不够长。(此外,我可能会选择较小的数字,而不是从较小的数字开始。)这是我为数不多的几次更改公认答案的情况之一:)
0.644934
myfile << std::setprecision(9);