用大的int分割大的double

时间:2013-11-26 16:36:11

标签: c++ double numerical

我正在编码物理模拟,最近我遇到了异常结果。我设法调试我的程序,错误是在一个大的双重划分由一个大的int,形式的东西:

cout << my_large_double/my_large_int << endl

使用命令-10 ^ {9}的my_large_double,并且我的两个整数的乘积是10 ^ {9}的顺序返回顺序为1的正数。 我通过在分母中加倍转换来修复它:

cout << my_large_double/( (double)my_large_int1*my_large_int2) << endl

但我想知道错误来自何处,是否有办法阻止它们发生?

更新:我在第一个问题中跳过了一个重要的细节:int实际上是两个整数的乘积。

2 个答案:

答案 0 :(得分:4)

这取决于表达式的确切编写方式。

如果你这样写:

my_large_double / my_large_int1 / my_large_int2

然后它相当于:

(my_large_double / my_large_int1) / my_large_int2

应该给你合理准确的结果;在第一次分组之前,my_large_int1被提升为double,在第二次分组之前,my_large_int2被提升为double

如果你这样写:

my_large_double / (my_large_int1 * my_large_int2)

然后乘法是在两个整数变量的类型中完成的,并且根据它们的值你可以有一个溢出(这可以给你一个比数学产品小得多的值 - 虽然严格来说有符号整数的行为溢出是未定义的。)

要记住的重要一点是,在大多数情况下,每个C表达式都是有效的单独评估;它的类型不受其出现的上下文的影响。表达式my_large_int1 * my_large_int2是整数乘法,即使结果是浮点除法的操作数或分配给浮点变量。

操作数都是整数的任何操作都是整数运算。如果一个操作数为double而另一个操作数为int,则int操作数将提升为double

即便如此:

double temp = my_large_int1 * my_large_int2;
... my_large_double / temp ...
在使用结果初始化temp之前,

将执行整数乘法,并且:

my_large_double / (double)(my_large_int1 * my_large_int2)

有同样的问题。

正如您所发现的,解决方案是将一个或两个整数操作数强制转换为double

my_large_double / ((double)my_large_int1 * (double)my_large_int2)

(你也可以投两者,只是为了对称和清晰。)

答案 1 :(得分:1)

IEEE format double可以容纳int而不会导致高达53位的精度损失,而int的典型值为31位。你的解决方案很好,预先转换为double,这样你就不会在乘法中遇到整数溢出。