C 转换 double ->long -> Short (使用右移 ">>")

标签 c casting bit-manipulation bitwise-operators

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

我的数组中有 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

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 比下一个更大的 double 更接近 105349120,因此它正确地向下舍入为 105349120.

但是,当我们再次减去时,105349120 - 63897600.000000007 会向下舍入,因为下一个比 41451520 更小的 double 是 (nextafter(41451520.0, 0))41451519.999999992549...。将它们放在一起:

41451519.999999992549...
41451519.999999993

是的,比 41451520 本身更接近 41451520 下面的第一个 double 。因此它正确地向下舍入为 41451519.999999992549...

当您将 41451519.999999992549... 转换为整数时,它会对数字进行取整,导致结果比您预期的值少 1。


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

关于C 转换 double ->long -> Short (使用右移 ">>"),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39588393/

相关文章:

c++ - OpenCV:C++ API 和 C API 在功能或速度上有区别吗?

casting - Neo4j:spring-data-neo4j,如何将结果转换为我的类型类?

php - 在 PHP 中将 Int 转换为 4 字节字符串

c - 找到下一个除以 8 的数字?

java - LevelDB 的默认比较器

c - 使用共享内存在两个进程之间传递套接字描述符

c - C 中的宏指令——我的代码示例不起作用

c - vsscanf 读取长度

casting - 如何计算 float 的小数位?

php - Laravel Eloquent 属性转换不起作用