c ++中长整数除法的上限

时间:2016-05-10 20:07:52

标签: c++ integer long-integer ceil

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

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整除的整数上 长长的上限是~10 ^ 18 那么是什么导致了这个错误?

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

2 个答案:

答案 0 :(得分:2)

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

浮点减法也可能是一个问题,特别是如果这两个数字的幅度几乎相同。如果两个输入都是(例如)50位,但前40位是相同的,那么它们将被取消,结果只有大约10位。

所以,首先,你可能希望用long long进行所有数学计算,如果这是你想要的结果类型。其次,您可能至少要考虑重新安排(a-b)/ca/c-b/c,以尽可能延迟减法。

答案 1 :(得分:0)

如果您知道两个值均为正数,则可以使用以下公式计算纯整数(或长整数)的ceil:

    (x + y-1)/y

所以,在你的情况下:

    (a - b + c-1)/c

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