草庐IT

math - float 学坏了吗?

coder 2024-03-21 原文

考虑以下代码:

0.1 + 0.2 == 0.3  ->  false
0.1 + 0.2         ->  0.30000000000000004

为什么会出现这些错误?

最佳答案

二进制 floating point数学就是这样。在大多数编程语言中,它基于 IEEE 754 standard .问题的症结在于,数字以这种格式表示为整数乘以 2 的幂;分母不是2的幂的有理数(如0.1,即1/10)无法精确表示。

对于 0.1在标准中binary64格式,表示可以完全写成

  • 0.1000000000000000055511151231257827021181583404541015625十进制,或
  • 0x1.999999999999ap-4C99 hexfloat notation .

相比之下,有理数0.1 ,即 1/10 , 可以完全写成

  • 0.1十进制,或
  • 0x1.99999999999999...p-4在 C99 hexfloat 符号的模拟中,...代表 9 的无限序列。

常量 0.20.3在你的程序中也将是它们真实值的近似值。碰巧最近的 double0.2大于有理数0.2但最接近的 double0.3小于有理数0.3 . 0.1的总和和 0.2结果大于有理数 0.3因此不同意您代码中的常量。

相当全面地处理浮点运算问题是 What Every Computer Scientist Should Know About Floating-Point Arithmetic .有关更易于理解的解释,请参阅 floating-point-gui.de .

Side Note: All positional (base-N) number systems share this problem with precision

普通的旧十进制(基数为 10)数字也有同样的问题,这就是为什么像 1/3 这样的数字最终会变成 0.333333333...

您刚刚偶然发现了一个数字 (3/10),它恰好很容易用十进制表示,但不适合二进制系统。它也是双向的(在某种程度上):1/16 是一个难看的十进制数字 (0.0625),但在二进制中它看起来和十进制中的第 10,000 一样整洁 (0.0001)** - 如果我们在在我们的日常生活中习惯使用以 2 为底的数字系统,你甚至会看到这个数字并本能地理解你可以通过将某物减半,再减半,一次又一次地到达那里。

当然, float 在内存中的存储方式并非如此(它们使用一种科学记数法)。然而,它确实说明了二进制浮点精度错误往往会出现这一点,因为我们通常感兴趣的“现实世界”数字通常是十的幂——但这只是因为我们使用十进制数字系统日——今天。这也是为什么我们会说 71% 而不是“每 7 个中有 5 个”(71% 是一个近似值,因为 5/7 不能用任何小数精确表示)。

所以不:二进制 float 并没有被破坏,它们只是碰巧和其他所有以 N 为基数的数字系统一样不完美:)

Side Side Note: Working with Floats in Programming

在实践中,这个精度问题意味着您需要使用舍入函数将 float 舍入到您感兴趣的小数位数,然后再显示它们。

您还需要用允许一定容差的比较替换相等性测试,这意味着:

if (x == y) { ... }

改为执行 if (abs(x - y) < myToleranceValue) { ... } .

哪里abs是绝对值。 myToleranceValue需要为您的特定应用程序选择 - 这将与您准备允许的“摆动空间”有很大关系,以及您要比较的最大数字可能是多少(由于精度问题的损失) ).当心您选择的语言中的“epsilon”样式常量。这些不能用作公差值。

关于math - float 学坏了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53494917/

有关math - float 学坏了吗?的更多相关文章

  1. ruby-on-rails - 32651 :ERROR comparison of Float with Float failed ruby - 2

    我是Rails的新手,我遇到了一个错误,但我似乎找不到问题所在。这是日志:[32651:ERROR]2012-10-0913:46:52::comparisonofFloatwithFloatfailed[32651:ERROR]2012-10-0913:46:52::/home/sunny/backend/lib/analytics/lifetime.rb:45:in`each'/home/sunny/backend/lib/analytics/lifetime.rb:45:in`max'/home/sunny/backend/lib/analytics/lifetime.rb:45

  2. ruby - 为什么在 Ruby 中是 Float::INFINITY == Float::INFINITY? - 2

    在数学中,2个无穷大既不等于,也不大于或小于then。那么是什么给了?在irb中,Float::INFINITY==Float::INFINITY(在ruby​​1.9.3中测试) 最佳答案 用更专业的术语来说,这一切都归结为浮点运算的IEEE754标准。TheIEEE754standarddoesimplicitlydefineInfinity==Infinitytobetrue.Therelevantpartofthestandardissection5.7:"Fourmutuallyexclusiverelationsarep

  3. ruby - 强制 Ruby 不以标准形式/科学记数法/指数记数法输出 float - 2

    我遇到了同样的问题here对于python,但对于ruby​​。我需要输出这样一个小数字:0.00001,而不是1e-5。有关我的特定问题的更多信息,我正在使用f.write("Mynumber:"+small_number.to_s+"\n")输出到一个文件对于我的问题,准确性不是什么大问题,所以只做一个if语句来检查是否small_number那么更通用的方法是什么? 最佳答案 f.printf"Mynumber:%.5f\n",small_number您可以将.5(小数点右侧5位数字)替换为您喜欢的任何特定格式大小,例如,%8

  4. ruby - 使用 Ruby 将输入值适本地转换为整数或 float - 2

    我相信我对这个问题有一个很好的答案,但我想确保ruby​​-philes没有更好的方法来做到这一点。基本上,给定一个输入字符串,我想在适当的情况下将该字符串转换为整数,或在适当的情况下将其转换为float。否则,只返回字符串。我会在下面发布我的答案,但我想知道是否有更好的方法。例如:to_f_or_i_or_s("0523.49")#=>523.49to_f_or_i_or_s("0000029")#=>29to_f_or_i_or_s("kittens")#=>"kittens" 最佳答案 我会尽可能避免在Ruby中使用正则表达式

  5. ruby - 比较 rspec 中的 float 时的奇怪行为 - 2

    以下测试中的第3个失败:specify{(0.6*2).shouldeql(1.2)}specify{(0.3*3).shouldeql(0.3*3)}specify{(0.3*3).shouldeql(0.9)}#thisonefails这是为什么呢?这是浮点问题还是ruby​​或rspec问题? 最佳答案 从rspec-2.1开始specify{(0.6*2).shouldbe_within(0.01).of(1.2)}在那之前:specify{(0.6*2).shouldbe_close(1.2,0.01)}

  6. ruby - 猴子修补 float 中缀运算符产生意想不到的结果 - 2

    重新定义Float#/似乎没有效果:classFloatdef/(other)"magic!"endendputs10.0/2.0#=>5.0但是当另一个中缀运算符Float#*被重新定义时,Float#/突然采用了新的定义:classFloatdef/(other)"magic!"enddef*(other)"spooky"endendputs10.0/2.0#=>"magic!"我很想知道是否有人可以解释这种行为的来源,以及其他人是否得到相同的结果。ruby:ruby2.0.0p353(2013-11-22)[x64-mingw32]要快速确认错误,请运行thisscript.

  7. ruby - 如何检查一个值是否是 Integer()、Float() 或 Rational() 的有效输入? - 2

    这大致基于“HowtoconvertaStringtoIntegerorFloat”。如果我想使用Ruby的内置转换机制将数字字符串输入转换为其“最合适的类型”,我可以这样做:defconvert(input)value=Integer(input)rescuenilvalue||=Float(input)rescuenilvalue||=Rational(input)rescuenilvalueendconvert('1')#=>1convert('1_000')#=>1000convert('0xff')#=>255convert('0.5')#=>0.5convert('1e2'

  8. ruby - 如何强制 Float 在不使用科学记数法的情况下以完全精确的方式显示,而不是作为字符串显示? - 2

    在Ruby中,如何在没有科学记数法的情况下强制显示所有重要位置/完全精确的float?目前我将BigDecimal转换为Float,BigDecimal(0.000000001453).to_f,但这会产生1.453e-09的结果float。如果我执行类似"%14.12f"%BigDecimal("0.000000001453").to_f的操作,我会得到一个字符串。然而,在这种情况下,字符串作为输出是NotAcceptable,因为我需要它作为没有科学记数法的实际数字float。---编辑---好吧,让我在这里提供一些背景信息,这可能需要更改我原来的问题。我正在尝试使用Highsto

  9. ruby - 从 float 中删除科学记数法 - 2

    我目前正在将两个float相乘:0.0004*0.0000000000012=4.8e-16如何获得正常格式的结果,即没有科学记数法,例如0.0000000000324,然后将其四舍五入为5个数字。 最佳答案 您可以使用stringformatting.a=0.0004*0.0000000000012#=>4.8e-16'%.5f'%a#=>"0.00000"pi=Math::PI#=>3.141592653589793'%.5f'%pi#=>"3.14159" 关于ruby-从floa

  10. ruby - 如何将 float 格式化为一定数量的小数和整数? - 2

    我正在尝试将Ruby中的float格式化为四位数字,包括小数点。例如:1=>01.002.4=>02.401.4455=>01.45现在,我正在尝试按如下方式格式化float:str_result="%.2f"%result这成功地将小数位数限制为两位。我还知道:str_result="%2d"%result它成功地将1转换为01,但丢失了小数位。我试着像这样组合这些:str_result="%2.2f"%result没有明显效果。它与%.2f具有相同的结果。有没有办法强制Ruby将字符串格式化为这种四位数格式? 最佳答案 您可以使

随机推荐