当前位置: 首页 > 知识库问答 >
问题:

为什么浮点数不准确?

邵绪
2023-03-14
32-bit "single precision" float: 9.19999980926513671875
64-bit "double precision" float: 9.199999999999999289457264239899814128875732421875

这样一个看似简单的数字怎么会“太大”而无法在64位内存中表达呢?

共有1个答案

彭硕
2023-03-14

在大多数编程语言中,浮点数的表示方式很像科学符号:有一个指数和一个尾数(也称为意义)。一个非常简单的数字,比如9.2,实际上是这个分数:

5179139571476070*2-49

其中指数为-49,尾数为5179139571476070。不可能用这种方式表示一些十进制数的原因是指数和尾数都必须是整数。换句话说,所有浮点数必须是整数乘以2的整数次方。

python prettyprint-override">def float_to_bin_parts(number, bits=64):
    if bits == 32:          # single precision
        int_pack      = 'I'
        float_pack    = 'f'
        exponent_bits = 8
        mantissa_bits = 23
        exponent_bias = 127
    elif bits == 64:        # double precision. all python floats are this
        int_pack      = 'Q'
        float_pack    = 'd'
        exponent_bits = 11
        mantissa_bits = 52
        exponent_bias = 1023
    else:
        raise ValueError, 'bits argument must be 32 or 64'
    bin_iter = iter(bin(struct.unpack(int_pack, struct.pack(float_pack, number))[0])[2:].rjust(bits, '0'))
    return [''.join(islice(bin_iter, x)) for x in (1, exponent_bits, mantissa_bits)]
>>> float_to_bin_parts(9.2)
['0', '10000000010', '0010011001100110011001100110011001100110011001100110']
    null

尾数以52位的形式存储在第三分量中。然而,这个组件也有一个怪癖。为了理解这个怪癖,考虑一下科学符号中的一个数字,如下所示:

6.0221413x1023

尾数为6.0221413。回想一下,科学记数法中的尾数总是以单个非零数字开始。对于binary也是如此,只是binary只有两个数字:01。所以二进制尾数总是以1开始!存储浮点数时,省略二进制尾数前面的1,以节省空间;我们必须把它放在第三个元素的前面,才能得到真正的尾数:

    null

1.14999999999999999999 x 23(不精确!)

并相乘以显示我们开始使用的数字(9.2)作为浮点值存储后的最终表示形式:

9.1999999999999993

5179139571476070/249

乘指数:

5179139571476070/562949953421312

>>> float_to_bin_parts(9.5)
['0', '10000000010', '0011000000000000000000000000000000000000000000000000']

二进制到十进制:

19 x 2-1

对除的负指数:

    null
 类似资料:
  • 但如果将浮点数或整数减小或增大一定量,则比较运行得快得多: 更改比较运算符(例如,改用或)不会以任何明显的方式影响时间。 这不仅仅与幅度有关,因为选择较大或较小的值会导致更快的比较,所以我怀疑这是由于位排列的某种不幸方式造成的。

  • 由于某些原因,这部分不起作用: 我将错误“无法将«类ocid»id«数据optr000000003701000000000000»转换为类型编号。(错误-1700)” 你知道为什么会这样吗?我想这是因为它不想让我把浮点和整数结合起来。如果这是原因,为什么?我该如何修复它?如果这不是问题,你认为是什么? 谢谢!

  • 问题内容: 当我使用交叉工具链编译C代码时,链接程序将显示警告页面,其中指出我的可执行文件使用硬浮点,而我的libc使用软浮点。有什么不同? 问题答案: 硬浮点使用片上浮点单元。软浮点在软件中模拟一个。区别在于速度。看到两者都在同一目标体系结构上使用,这很奇怪,因为该芯片要么具有FPU,要么没有FPU。您可以使用- msoft-float在GCC中启用软浮点。您可能需要重新编译libc以使用硬件浮

  • 问题内容: 输出: 为什么这样的输出?我期望作为第一种情况的结果。 问题答案: 区别在于6.5可以完全以float和double表示,而3.2不能完全以两种类型表示。并且两个最接近的近似是不同的。 float和double之间的相等比较首先将float转换为double,然后将两者进行比较。因此数据丢失。 您不应该比较浮点数或双精度数是否相等。因为您不能真正保证分配给float或double的数字

  • 问题内容: 众所周知,(大多数)浮点数没有精确存储(使用IEEE-754格式时)。因此,不应这样做: ......因为它会导致,除非一些特定的任意精度的类型/类使用(BigDecimal的中的Java/Ruby的,bcmath时在PHP中,[数学::BigInt有 / 数学::BigFloat在Perl,仅举几例)来代替。 但是,我想知道为什么当尝试打印该表达式的结果时,脚本语言(Perl和PHP

  • 问题内容: 问题很简单而且简短:为什么要清除浮动?我查看了w3标准文档,但没有任何暗示。 问题答案: 因为当您与其他任何东西一起使用时会建立一个新的块格式设置上下文(链接到w3.org规范)。