c中浮点的精确表示

时间:2010-11-29 17:15:45

标签: c floating-point

void main()
{
    float a = 0.7;

    if (a < 0.7)
        printf("c");
    else
        printf("c++");
} 

在0.7的上述问题中,将打印“c”,但对于0.8,将打印“c ++”。为什么呢?

如何以二进制形式表示浮动?

在某些地方,提到内部0.7将存储为0.699997,但0.8存储为0.8000011。为什么这样?

9 个答案:

答案 0 :(得分:12)

基本上使用float,你得到32位编码

VALUE   = SIGN * MANTISSA * 2 ^ (128 - EXPONENT)
32-bits = 1-bit  23-bits               8-bits

并存储为

MSB                    LSB
[SIGN][EXPONENT][MANTISSA]

因为你只得到23位,这就是你可以存储的“精度”。如果您试图表示在基数2中不合理(或重复)的分数,则位序列将在第23位“舍入”。

0.7 base 10是7/10,二进制是0b111 / 0b1010你得到:

0.1011001100110011001100110011001100110011001100110011... etc

由于这种情况重复,因此在固定精度下无法准确表示它。该 同样适用于0.8,二进制是:

0.1100110011001100110011001100110011001100110011001101... etc

要查看这些数字的固定精度值是什么,你必须以你的位数“切断它们”并进行数学计算。唯一的技巧是你隐含的前导1并没有存储,所以你在技术上获得了额外的精度。由于舍入,最后一位将为1或0,具体取决于截断位的值。

因此,0.7的值实际上是11,744,051 / 2 ^ 24(无舍入效应)= 0.699999988,而0.8的值实际上是13,421,773 / 2 ^ 24(四舍五入)= 0.800000012。

这就是它的全部内容:)

答案 1 :(得分:10)

对此的一个很好的参考是What Every Computer Scientist Should Know About Floating-Point Arithmetic。如果需要,可以使用更高精度类型(例如double)或二进制编码十进制(BCD)库来获得更好的浮点精度。

答案 2 :(得分:4)

内部代表是IEE754

您也可以使用this calculator将十进制转换为浮点数,我希望这有助于理解格式。

答案 3 :(得分:0)

float将按照IEEE 754:1位中的符号进行存储,8表示偏置指数,其余存储小数部分。

将数字表示为浮点数作为数字线上的点,相隔一定距离;通常,小数部分将落在这些点之间,并且将使用最近的表示;这会导致您描述的违反直觉的结果。

"What every computer scientist should know about floating point arithmetic"应该详细回答您的所有问题。

答案 4 :(得分:0)

如果您想知道C(以及几乎所有语言)中的float / double是如何呈现的,请参考标准浮点运算(IEEE 754)http://en.wikipedia.org/wiki/IEEE_754-2008

Using single-precision floats as an example, here is the bit layout:  
seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm    meaning  
31                              0    bit #  
s = sign bit, e = exponent, m = mantissa

答案 5 :(得分:0)

另一个很好的资源,可以看到浮点数如何在计算机中存储为二进制文件,这是Wikipedia在IEEE-754上的页面。

答案 6 :(得分:0)

C / C ++中的浮点数以IEEE-754标准格式表示。互联网上有很多文章,它们比我在这里描述得更详细,如何用二进制表示一个浮点。对IEEE-754的简单搜索应该可以解释这个谜团。

答案 7 :(得分:0)

0.7是一个数字文字;它的值是数学实数0.7,四舍五入到最接近的双精度值。

初始化浮点数a = 0.7后,a的值为0.7舍入为浮点数,即实数0.7,舍入到最接近的double值,四舍五入到最接近的浮点值。除了一个巨大的巧合,你不会指望a等于0.7。

“if(a&lt; 0.7)”将0.7舍入为双倍然后浮动,数字0.7舍入为double。似乎在0.7的情况下,舍入产生较小的数字。并且在0.8的相同实验中,将0.8舍入到浮点将产生大于0.8的数字。

答案 8 :(得分:-2)

浮点比较可靠,无论你做什么。您应该使用阈值容忍比较/ epsilon浮点比较。

尝试IEEE-754 Floating-Point Conversion,看看你得到了什么。 :)