我有一个小代码做一些数字转换我想把一个数字从double变成long,然后用右移把它转换成short但它给了我不同的结果,我不知道为什么。
我在一个数组中有3个数字,我使用for循环对它们求和,每次我将结果转换为short
有一个数字的.000000007更准确地63897600.000000007把这个加在总数上,然后再减去它,会得到不同的结果。
我不明白为什么会发生这种情况,也不知道如何处理这个特殊的案件。
这是我的代码:

#include <stdio.h>

#define DOUBLETOLONG(number)   (long)(number)
#define NEAREST(number)        ((short)((number + 32768) >> 16))
#define LONGTOSHORT(number)    NEAREST(DOUBLETOLONG(number))

int main() {
    int k = 0;
    double array[3] ={ 41451520.000000, 63897600.000000007, -63897600.000000007 };
    double total_x = array[0];
    short j = LONGTOSHORT(total_x);

    printf("j = %d\n", j);

    for (k = 1; k < 3; k++) {
        total_x = total_x+array[k];
        j = LONGTOSHORT(total_x);
        printf("j = %d\n", j);
    }
    return 0;
}

结果如下:
j = 633
j = 1608
j = 632

最佳答案

41451520+63897600=105349120
在adouble中,这个整数仍然可以精确地表示但是,我们没有考虑分数部分0.000000007让我们检查下一个最大的double是什么:

#include <stdio.h>
#include <math.h>

int main(int argc, char** argv) {
    printf("%.23f\n", nextafter(105349120.0, INFINITY));
    return 0;
}

结果,是105349120.000000014901...让我们把这些放在一起:
105349120.000000014901...
        0.000000007

这意味着105349120.000000007比下一个更大的105349120更接近double,因此它正确地向下舍入到105349120
然而,当我们再次相减时,105349120 - 63897600.000000007会四舍五入,因为下一个小于41451520的双精度数是(nextafter(41451520.0, 0)41451519.999999992549...把他们放在一起:
41451519.999999992549...
41451519.999999993

是的,比自身更接近前两倍所以它正确地被舍入到41451520
当您将41451520转换为整数时,它会将数字设为楼层,结果比您期望的值少一个。
浮点数学充满了惊喜你应该读What Every Computer Scientist Should Know About Floating-Point Arithmetic,但现在可能还是太高级了但重要的是要意识到,是的,浮点运算充满了惊喜,但不,它不是魔术,你可以学习陷阱。

08-16 21:21