考虑以下代码:
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-4在 C99 hexfloat notation .相比之下,有理数0.1 ,即 1/10 , 可以完全写成
0.1十进制,或0x1.99999999999999...p-4在 C99 hexfloat 符号的模拟中,...代表 9 的无限序列。常量 0.2和 0.3在你的程序中也将是它们真实值的近似值。碰巧最近的 double至 0.2大于有理数0.2但最接近的 double至 0.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/
我是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个无穷大既不等于,也不大于或小于then。那么是什么给了?在irb中,Float::INFINITY==Float::INFINITY(在ruby1.9.3中测试) 最佳答案 用更专业的术语来说,这一切都归结为浮点运算的IEEE754标准。TheIEEE754standarddoesimplicitlydefineInfinity==Infinitytobetrue.Therelevantpartofthestandardissection5.7:"Fourmutuallyexclusiverelationsarep
我遇到了同样的问题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
我相信我对这个问题有一个很好的答案,但我想确保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中使用正则表达式
以下测试中的第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)}
重新定义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.
这大致基于“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'
在Ruby中,如何在没有科学记数法的情况下强制显示所有重要位置/完全精确的float?目前我将BigDecimal转换为Float,BigDecimal(0.000000001453).to_f,但这会产生1.453e-09的结果float。如果我执行类似"%14.12f"%BigDecimal("0.000000001453").to_f的操作,我会得到一个字符串。然而,在这种情况下,字符串作为输出是NotAcceptable,因为我需要它作为没有科学记数法的实际数字float。---编辑---好吧,让我在这里提供一些背景信息,这可能需要更改我原来的问题。我正在尝试使用Highsto
我目前正在将两个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
我正在尝试将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将字符串格式化为这种四位数格式? 最佳答案 您可以使