C铸造双 - >长 - >短(使用右移“>>”)

时间:2016-09-20 07:42:53

标签: c casting bit-manipulation bitwise-operators

我有一个小代码可以进行一些数字转换。我想将一个数字从double变为long,然后使用右移位将其转换为short。但它给了我不同的结果,我不知道为什么。

我在数组中有3个数字,我使用pb->show()循环来计算它们的总和,每次我将结果转换为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;
}

1 个答案:

答案 0 :(得分:2)

41451520 + 63897600 = 105349120

double中,这个整数仍然可以准确表示。但是,我们没有考虑小数部分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本身。所以它正确地向下舍入到41451519.999999992549...

当您将41451519.999999992549...转换为整数 floor 时,会导致比您预期的更少。

浮点数学充满惊喜。你应该阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic,但也许它现在还是太先进了。但重要的是要注意,是的,浮点充满惊喜,但不是它不是魔法,你可以了解陷阱。