将大的double除以大的int

Dividing large double by large int

本文关键字:int double      更新时间:2023-10-16

我正在编写一个物理模拟,最近遇到了异常结果。我设法调试了我的程序,错误是一个大的double除以一个大int,形式如下:

cout << my_large_double/my_large_int << endl

对于-10^{9}阶的my_large_double和10^{9}阶的两个int的乘积,返回的是1阶的正数。我通过在分母中强制转换为双倍来修复它:

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

但我想知道错误是从哪里来的,有没有办法防止它们通常发生?

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

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

如果你写这个:

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)

(为了对称和清晰起见,您还可以同时铸造它们。)

IEEE格式的double最多可容纳53位的int,而int通常为31位。您的解决方案很好,可以提前转换为double,这样您就不会在乘法中遇到整数溢出。

相关文章: