Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C/C++双数算术表达式-奇怪的结果-java翻译_Java_C++_C_Double_Arithmetic Expressions - Fatal编程技术网

C/C++双数算术表达式-奇怪的结果-java翻译

C/C++双数算术表达式-奇怪的结果-java翻译,java,c++,c,double,arithmetic-expressions,Java,C++,C,Double,Arithmetic Expressions,第一个问题 在C代码中,我有一个表达式: double completeExpression = x1 - h*exp(-lambda*t); 我将其分为两个操作: double value = h*exp(-lambda*t); double subtraction = x1 - value; 问题是减法与completeExpression不同。 怎么了 我在代码中用以下几行代码复制了一个奇怪的结果: const double TOLERANCE = 1e-16; double h =

第一个问题

在C代码中,我有一个表达式:

double completeExpression  = x1 - h*exp(-lambda*t);
我将其分为两个操作:

double value = h*exp(-lambda*t);
double subtraction = x1 - value;
问题是减法与completeExpression不同。 怎么了

我在代码中用以下几行代码复制了一个奇怪的结果:

const double TOLERANCE = 1e-16;
double h = 0.51152525298500628;
double lambda =0.99999999999999978;
double t=0.1;
double x1 =0.4628471891711442 ;

double completeExpression  = x1 - h*exp(-lambda*t);
double value = h*exp(-lambda*t);
double subtraction = x1 - value;

printf("x1 = %1.4e & value = %1.4e",x1,value);
printf("\ncompleteExpression = %1.4e",completeExpression);
printf("\nsubtraction = %1.4e",subtraction);
结果:

x1 = 4.6285e-001 & value = 4.6285e-001
completeExpression = 8.2779e-017
subtraction = 5.5511e-017
第二个问题:

我必须用Java翻译completeExpression,并且我总是返回坏结果减法和not completeExpression值:

代码:


与整数不同的浮点数几乎永远不会完全相同。原因在于它们与尾数和指数一起存储的方式

最后,在对两个浮点数执行相同的操作后,您永远无法确保它们是相同的。更重要的是,IFM减法=completeExpression通常无效。相反,你应该寻找一个接近的匹配:

if( abs(subtraction - completeExpression) < TOLERANCE )
其中,公差是一个常数,比如常数双公差=1e-16

有关为什么浮点数近似的更多信息,请阅读关于浮点数的。但基本原因是,由浮点值表示的数字范围远远大于可以编码到给定空间中的位数

32位整数可以对从-2GB到+2GB的值进行编码,但32位浮点的范围是从-3.4e38到+3.4e38。这是一个超过20位的范围差

对于64位值,范围差甚至更大,几乎为300位

扩展范围是有代价的——32或64位空间的一部分用于表示二进制的精度数字,而不是十进制的精度数字,这些数字的数量限制了浮点数的最终精度


一般来说,以浮点IEEE 754二进制格式表示的两个数字123e456和1.23e458仍然会不同,即使它们在数学上是绝对相等的。

检查这一点:在处理非整数浮点计算不精确时,看起来像是一个非常常见的计算裕度;因此,依靠精确的结果,例如两个数字的测试不相等是一个坏主意。如果您提高printfs的精度,您也应该能够看到其中的差异。I,您使用的是哪种编译器?请尝试仅用16个小数位数来表示数学上精确的1/7实值。问题不是尾数和指数组合所能表示的小数位数,但这个数字只能用尾数来表示。除了0.1之外,OP的原始帖子中的数字看起来都是不精确的。我会重新写下我的答案,让这一点更清楚,我同意——尾数是限制数字的因素precision@YePhlcK谢谢你的建议,我编辑了代码。不幸的是,问题总是存在的true@michele-试着玩弄宽容。最有可能的是你需要增加它,我不知道确切的价值,这是足够好的,为您的特殊application@YePhlcK这些值用于其他表达式,最终结果是,对于特定的输入组合,结果差异更大。
#gcc --version

My Gcc Version:
$ gcc --version
gcc.exe (GCC) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
if( abs(subtraction - completeExpression) < TOLERANCE )