跳至主要內容

06. 编程语言 - 缺陷篇

LincZero大约 1 分钟

06. 编程语言 - 缺陷篇

目录

[toc]

0.1+0.2 = 0.30000000000000004

参考:https://www.runoob.com/manual/pythontutorial3/docs/html/floatingpoint.html

  • 类似情况,相同原理的还有:

    • 运算结果为0.3时
      • 3*0.1 = 0.30000000000000004 != 0.3
    • 浮点加减运算
      • 50.25f + 11.17f = 61.419998
      • 50.25f - 11.14f = 39.080002
  • 普遍性

    • 所有语言都存在这种问题(亲测pythonjavascript存在)
    • 但计算器一般不会这样(亲测casio fx82uTools计算稿纸微软计算器安卓多多计算器无该问题)
  • 原理(以双浮点为例,小数点后面有效数字16位)

    • 0.1 = 0.0001100110011001
    • 0.2 = 0.0011001100110011
    • 0.3 = 0.0100110011001100
    • 0.1+0.2 = 0.0100110011001100 = 0.3
    • 即:0.3=0.01001100110011000.30.3 = 0.0100110011001100\neq 0.3
  • 解决方案

    • 比如Python中,float.as_integer_ratio()open in new window 方法以分数的形式表示一个浮点数的值:

      >>> x = 3.14159
      >>> x.as_integer_ratio()
      (3537115888337719, 1125899906842624)
      >>> x == 3537115888337719 / 1125899906842624
      True
      
    • float.hex()open in new window 方法以十六进制表示浮点数,给出的同样是计算机存储的精确值:

      >>> x.hex()
      '0x1.921f9f01b866ep+1'
      >>> x == float.fromhex('0x1.921f9f01b866ep+1')
      True
      
    • 另外一个有用的工具是 math.fsum()open in new window 函数,它帮助求和过程中减少精度的损失。当数值在不停地相加的时候,它会跟踪“丢弃的数字”。这可以给总体的准确度带来不同,以至于错误不会累积到影响最终结果的点:

      >>> sum([0.1] * 10) == 1.0
      False
      >>> math.fsum([0.1] * 10) == 1.0
      True
      

手持两把锟斤拷 口中疾呼烫烫烫 脚踏千朵屯屯屯 笑看万物锘锘锘

  • C语言