有2个大整数。当我乘以它时,结果总是错误的,即使我使用了long double并且结果应该在long double的有效范围内:
long double f = 1000000000 * 99999;
我调试了,结果是如此奇怪: -723552768.00000000 。我错过了什么吗?我该如何倍数?
谢谢!
答案 0 :(得分:4)
根据C ++标准:
4一个不带后缀的浮点常量的类型为double。如果以 字母f或F,其类型为float。如果以字母L或L结尾, 的类型为long double
auto fl = 1000000000.L * 99999.L;
std::cout << fl << "\n";
或
long double fl = 1000000000L * 99999.L;
std::cout <<"\n"<< fl << "\n";
答案 1 :(得分:2)
在C ++中,数字文字默认为int
。因此,表达式1000000000 * 99999
被视为两个int
的乘积,因此*运算符返回的结果为int
。仅在乘法发生之后将此int
转换为long double
变量f
。根据您的平台,int
的范围通常是-2147483648至2147483647(或4个字节)。但是,1000000000 x 99999的乘积为9.9999 x 10 ^ 13,不在此范围内,因此由于int
变量不足以容纳该值而发生溢出。
为避免这种情况,应将*运算符所操作的至少一个数字声明为后缀为long double
或.l
的{{1}}文字,如下所示:
.L
在上面的表达式中,*运算符将返回一个long double f = 1000000000.L * 99999
,其大小足以容纳分配给long double
的结果乘积。
答案 2 :(得分:1)
同意@feiXiang。您基本上是将两个整数相乘。要进行正确的计算,您必须将大数定义为long double。请参见下面的代码:
#include <iostream>
using namespace std;
int main()
{
long double a = 1000000000;
long double b = 99999;
long double f = a * b;
cout<<f;
return 0;
}
输出:
9.9999e + 13
答案 3 :(得分:1)
实际上,您可以通过以下方式调用未定义的行为:
long double f = 1000000000 * 99999;
首先,求值1000000000 * 99999
,它是两个int
对象的乘积。将两个int
对象相乘始终是int
。由于int
的大小不足以表示结果(很可能是32位),因此高位丢失了。
由于带符号整数类型的溢出是未定义的,因此您刚刚触发了未定义的行为。但是在这种情况下,即使是UB,也可以解释发生了什么。
计算仅保留最低的32位,应为(1000000000 * 99999) modulo (2**32) == 3571414528
。但是对于int
,此值太大。由于在PC上,int负数由二进制补码表示,因此每次2**31<= result < 2**32
时,我们必须减去2 ** 32。这给出了-723552768
现在,最后一步是:
long double f = -723552768
这就是您所看到的。
要解决此问题,请像这样使用long long
:
long double f = 1000000000LL * 99999;
或double
:
long double f = 1000000000.0 * 99999;
答案 4 :(得分:0)
1000000000 和 99999 是整数,那么1000000000 * 99999的结果将是一个整数,然后将其分配给变量,结果超出范围整数。
您应确保结果是长双首:
long double f = (long double) 1000000000 * 99999;
或
long double f = 1000000000LL * 99999;