【问题标题】:Ceiling of Long Integer division in c++c++中长整数除法的上限
【发布时间】:2016-05-10 20:07:52
【问题描述】:

我试图解决一些涉及大数除法的问题。我偶然发现了使用以下方法得到错误结果的某些情况:

LL 结果 = (LL)ceil((double)(a-b)/c),其中 a,b 和 c 是长整数 (LL)。

#include <stdio.h>      /* printf */
#include <math.h>       /* ceil */
#define LL long long

int main ()
{
    LL a= 10000000000000000;
    LL aa = 10000000000000000-1;
    LL aaa = 10000000000000000+1;
    int b = 1;
    int c = 1;
    printf ( "%Ld\n", (LL)ceil((double)(a-b)/c) );
    printf ( "%Ld\n", (LL)ceil((double)(aa-b)/c) );
    printf ( "%Ld\n", (LL)ceil((double)(aaa-b)/c) );
    return 0;
}

Output:
10000000000000000
9999999999999998
10000000000000000

这开始发生在大于或等于 10^16 且可被 10 整除的整数上。
long long 的上限是~10^18。
那么是什么导致了这个错误呢?

我在 C++14 模式下使用 GCC 5.1(在 ideone.com 上)。

【问题讨论】:

  • 您使用的是什么平台和编译器?
  • 我尝试了 Ideone(C++ 14) 使用的编译器。这是代码的链接:ideone.com/aT6nem
  • 双精度为 52 位 = 15 位。
  • @stark 如果您将此添加为答案,我会投票赞成。

标签: c++ integer long-integer ceil


【解决方案1】:

如果你知道这两个值都是正数,你可以用纯整数(或 long long)计算 ceil:

    (x + y-1)/y

所以,在你的情况下:

    (a - b + c-1)/c

处理负数留给读者作为练习(它可能有点繁琐地决定你想要它做什么,而且你通常不需要它)。

【讨论】:

  • 谢谢。后来,在找出错误之后,我才转向这个。
【解决方案2】:

虽然它可以存储更大幅度的数字,但double 的典型实现只能保持大约 15-16 位的精度。

浮点减法也可能是个问题,尤其是当两个数字的大小几乎相同时。如果两个输入都是(比如说)50 位,但前 40 位是相同的,那么它们将被抵消,结果将只有大约 10 位。

因此,首先,您可能希望使用 long long 进行所有数学运算,如果这是您想要的结果类型。其次,您可能至少要考虑将您的 (a-b)/c 重新排列为 a/c-b/c 以尽可能长时间地延迟减法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    • 2020-04-15
    • 1970-01-01
    • 2021-01-16
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多