C / C ++带双数的算术表达式 - 奇怪的结果 - 在java中进行翻译

时间:2015-09-24 21:32:51

标签: 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 = 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,并且我总是返回错误的结果(减法)而不是completeExpression值:

代码:

 static double TOLERANCE = 1e-16;
   public static void main() {

        double h = 0.51152525298500628;
        double lambda =0.99999999999999978;
        double t=0.1;
        double x1 =0.4628471891711442 ;

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

        System.out.println( "x1 = " + String.format("%1.4e", value) + "& value = " + String.format("%1.4e",x1) );
        System.out.println("\ncompleteExpression = " + String.format("%1.4e",completeExpression));
        System.out.println("\nsubtraction = " + String.format("%1.4e",subtraction));
#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.

1 个答案:

答案 0 :(得分:1)

浮点数(与整数不同)几乎从不完全相同。原因在于它们的存储方式(使用尾数和指数)。

最后,在执行"相同"之后,您永远无法确定两个浮点数是否相同。对他们的操作。更重要的是 - if(subtraction!=completeExpression)通常无效。相反,你应该寻找一个"密切匹配":

if( abs(subtraction - completeExpression) < TOLERANCE )

其中TOLERANCE是常量,例如const double TOLERANCE = 1e-16;

有关为什么浮点数&#34;近似&#34;的更多信息您可以阅读Floating point上的Wiki。但基本原因是浮点值表示的数字范围远大于可编码到给定空间的数字位数。

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

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

扩展范围是有代价的 - 32或64位空间的一部分用于表示&#34;精度&#34;数字(二进制​​,不是十进制)和数字的数量是限制浮点数的最终精度。

一般来说,两个数字123e4561.23e458(以浮点IEEE 754二进制格式表示)仍然会有所不同,即使数学它们绝对是相等。