C语言中浮点数和整型数相乘的问题[重复]

eyh26e7m  于 2022-12-17  发布在  其他
关注(0)|答案(3)|浏览(384)

此问题在此处已有答案

(31个答案)
5天前关闭。
我使用的是在线编译器https://www.onlinegdb.com/,在下面的代码中,当我将2.1乘以100时,输出变为209而不是210。

#include<stdio.h>
#include <stdint.h>

int main() 
{
    float x = 1.8;

    x = x + 0.3;

    int coefficient = 100;

    printf("x: %2f\n", x);

    uint16_t y = (uint16_t)(x * coefficient);

    printf("y: %d\n", y);

    return 0;
}

我做错了什么?我应该怎么做才能得到210?
我尝试了所有不同的类型转换仍然不工作。

col17t5w

col17t5w1#

下面假设编译器对floatdouble使用IEEE-754 binary 32和binary 64,这是非常常见的。
float x = 1.8;
由于1.8是一个double常量,编译器会将1.8转换为最接近的double值1.800000000000000444089209850062616169452667236328125。然后,为了将其赋给floatx,编译器会将其转换为最接近的float值。1.7999999523162841796875.
x = x + 0.3;
编译器将0.3转换为最接近的double值0.299999999999999988897769753748434595763683319091796875。然后,它使用double算法将x与该值相加。其产生2.0999995231628400205181605997495353221893310546875。
然后,为了将其赋值给x,它将其转换为最接近的float值2.09999904632568359375。
uint16_t y = (uint16_t)(x * coefficient);
因为xfloatcoefficientint,所以编译器将coefficient转换为float,并使用float算法执行乘法,结果为209.9999847412109375。
然后转换为uint16_t会截断该数字,生成209。
得到210的一种方法是使用uint16_t y = lroundf(x * coefficient);。(lroundf<math.h>中声明。)然而,为了确定正确的方法,您应该解释这些数字是什么以及为什么要使用它们进行此运算。

3htmauhk

3htmauhk2#

浮点数并不精确,当您将1.8 + 0.3相加时,FPU可能会生成与预期的2.1略有不同的结果(差值小于浮点数Epsilon)阅读更多关于wiki https://en.wikipedia.org/wiki/Machine_epsilon中浮点数表示的信息
你的情况是
1.8+ 0.3 = 209.0999999 ...然后将其截断为整数,得到209
您可能会发现此问题也与您相关Why float.Epsilon and not zero?可能是

dgenwo3n

dgenwo3n3#

#include<stdio.h>
#include <stdint.h>
#include <inttypes.h>

int main() 
{
    float x = 1.8;

    x = x + 0.3;

    uint16_t coefficient = 100;

    printf("x: %2f\n", x);

    uint16_t y = round(x * coefficient);

    printf("y: %" PRIu16 "\n", y);

    return 0;
}

相关问题