在C中将double翻转为浮点数

aud*_*tic 5 c floating-point precision double floating-accuracy

这是一个非常简单的问题,但是一个重要问题,因为它极大地影响了我的整个项目.

假设我有以下代码snipet:

unsigned int x = 0xffffffff;
float f = (float)((double)x * (double)2.328306436538696e-010); //  x/2^32
Run Code Online (Sandbox Code Playgroud)

我希望它f像0.99999,但相反,它会向上舍入到1,因为它是最接近的float近似值.这不好,因为我需要float[0,1)区间的值,而不是[0,1].我确信这很简单,但我会感激一些帮助.

Cub*_*bbi 8

在C(自C99),则可以用改变舍入方向fesetroundlibm

#include <stdio.h>
#include <fenv.h>
int main()
{
    #pragma STDC FENV_ACCESS ON
    fesetround(FE_DOWNWARD);
    // volatile -- uncomment for GNU gcc and whoever else doesn't support FENV
    unsigned long x = 0xffffffff;
    float f = (float)((double)x * (double)2.328306436538696e-010); //  x/2^32
    printf("%.50f\n", f);
}
Run Code Online (Sandbox Code Playgroud)

使用IBM XL,Sun Studio,clang,GNU gcc进行测试.0.99999994039535522460937500000000000000000000000000在所有情况下,这都给了我


aud*_*tic 0

我最终的解决方案是缩小常数乘数的大小。这可能是最好的解决方案,因为无论如何乘以双倍是没有意义的。转换为浮点数后看不到精度。

所以2.328306436538696e-010改为2.3283063