代码之家  ›  专栏  ›  技术社区  ›  Nhan Phan

在C++中乘以2个大数有错误的结果

c++
  •  0
  • Nhan Phan  · 技术社区  · 7 年前

    有两个大整数。当我将其相乘时,结果总是错误的,即使我使用了long double,结果应该在long double的有效范围内:

    long double f = 1000000000 * 99999;
    

    我调试过,结果很奇怪: . 我错过什么了吗?我怎么能把它倍数?

    谢谢你的关心!

    5 回复  |  直到 7 年前
        1
  •  4
  •   Seek Addo    7 年前

    从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";
    
        2
  •  2
  •   Christopher Conroy    7 年前

    数字文本是 int 默认情况下,在C++中。因此,表达式 1000000000 * 99999 被视为二的乘法 ,因此*运算符返回的结果是 内景 . 这个 内景 仅转换为 long double 变量 f 在乘法运算之后。根据您的平台,范围 内景 通常从-2147483648到2147483647(或4字节大小)。然而,100000000 x 99999的乘积是9.9999 x 10^13,这超出了该范围,因此当 变量不够大,无法保存该值。

    长双 带后缀的文字 .l .L 具体如下:

    long double f = 1000000000.L * 99999
    

    在上面的表达式中,*运算符将返回 在分配给 f型

        3
  •  1
  •   Saboor    7 年前

    同意@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

        4
  •  1
  •   Michael Veksler    7 年前

    实际上,调用未定义的行为时使用:

    long double f = 1000000000 * 99999;
    

    首先,评估 1000000000 * 99999 ,这是2的乘法 int 物体。乘以2 内景 对象总是 内景 . 自从 大小不足以表示结果(最有可能是32位),高位将丢失。

    由于带符号整数类型中的溢出未定义,您刚刚触发了未定义的行为。但在这种情况下,有可能解释发生了什么,即使它是UB。

    计算只保留最低的32位,应该是 (1000000000 * 99999) modulo (2**32) == 3571414528 . 但是这个值太大了 内景 . 因为在PC上,int负数是用2的补码表示的,所以每次我们都要减去2**32 2**31<= result < 2**32 . 这是-723552768

    long double f = -723552768
    

    这就是你看到的。

    为了克服这个问题,或者使用 long long

    long double f = 1000000000LL * 99999;
    

    或者 double :

    long double f = 1000000000.0 * 99999;
    
        5
  •  0
  •   user10237405 user10237405    7 年前

    是整数,则100000000*99999的结果在分配给变量之前将是一个整数,并且结果超出整数范围。

    您应该确保结果是长双优先:

    long double f = (long double) 1000000000 * 99999;
    

    或者

    long double f = 1000000000LL * 99999;