首先,我不是用英语学习数学的,所以我可能会在我的课文中使用错误的单词。
浮点数可以是有限的(42.36)和无限的(42.363636...)
在 C/C 中,数字以 2 为基数存储。我们的大脑以 10 为基数操作浮点数。
问题是-
这在大多数情况下没有任何意义。 double 的最后一位数字可能会偏移 1 位 - 不是问题。
当我们计算两个实际上是整数的浮点数时,就会出现问题。 C 上的
我在 Python 中运行了一些测试,似乎浮点除法总是按预期结果。但是一些测试是不够的,因为问题是依赖于架构的。有人确定它是否得到处理,以及在什么级别 - 在浮点类型本身或仅在四舍五入和缩短函数中?
附言如果有人可以为我刚刚开始的 Haskell 澄清同样的事情 - 那就太好了。
更新
人们在一份官方文件中指出,浮点运算存在不确定性。剩下的问题是 - 像
C 和 C 用于表示 float 和 double 的格式是标准化的(IEEE 754),您描述的问题是该表示所固有的。由于 Python 是用 C 实现的,它的浮点类型容易出现相同的舍入问题。
Haskell 的 Float 和 Double 是一种更高级别的抽象,但由于大多数(全部?)现代 CPU 使用 IEEE754 进行浮点计算,您很可能也会在那里遇到这种舍入错误。
换句话说:只有选择不将其浮点类型基于底层架构的语言/库才能在一定程度上规避 IEEE754 舍入问题,但由于底层硬件不直接支持其他表示,必须有性能损失。因此,可能大多数语言都会坚持这个标准,尤其是因为它的局限性是众所周知的。
实数本身,包括浮点数,在任何数学意义上都不是"无限的"。它们可能有无限的十进制表示,但这只是我们编写它们(或将它们存储在计算机中)方式的技术问题。但事实上,IEEE754 也指定了 ∞ 和 -∞ 值,它们是实际的无穷大......但它们并不代表实数,并且在许多方面在数学上都相当可怕。
另外... "如果你把它转换成整数,那么" 你永远不应该 "convert" 浮点数转换成整数,这是不可能的:你只能将它们四舍五入成整数。如果你这样做,例如Haskell的
Prelude> round $ 99/3
33
虽然ghci用浮点计算除法。
唯一总是不安全的东西:
当然,从 float 到 int 的隐式转换是完全疯狂的,在 C 语言中肯定是一个错误。 Haskell 和 Python 都是正确的强类型,所以这样的事情不会偶然发生。
通常不应期望浮点数与任何特定值完全相等。无论如何,期望这样并不是真的有用,因为对于实际实数,任何一个都是空集,这大致意味着两个实数相等的唯一方法是如果有这么深的数学原因。但是对于任何发行版,例如从物理过程来看,相等的概率正好为零,那你为什么要检查呢?只有比较数字 OTOH 和
来"模拟"相等性
除了这里的其他精彩答案,粗略地说,无论您使用哪种语言与 IEEE754 交互,IEEE754 都有完全相同的问题,我想指出许多语言都有其他类型数字的库。一些标准方法是使用定点算术(IEEE754 的许多细微差别来自浮点)或有理数。 Haskell 还提供可计算实数和分圆数的库。
此外,由于其类型类机制,在 Haskell 中使用这些替代类型的数字特别方便,这意味着使用这些其他类型的数字进行算术运算的外观和感觉与您通常使用的 IEEE754 进行算术运算完全相同
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 33.0 > 99/3 :: Fixed E12 33.000000000000 > 99/3 :: Rational 33 % 1 > 99/3 :: CReal 33.0 > 99/3 :: Cyclotomic 33 > 98/3 :: Rational 98 % 3 > sqrt 2 :: CReal 1.4142135623730950488016887242096980785697 > sqrtInteger (-5) :: Cyclotomic e(20) + e(20)^9 - e(20)^13 - e(20)^17 |
Python 在内部将数字表示为 C 双精度数,因此您将遇到浮点运算固有的所有问题。但它也包括一些算法来"修复"明显的情况。您给出的示例 32.99999... 被识别为 33.0。从 Python 2.7 和 3.1 开始,他们使用 Gay\\'s 算法执行此操作;即四舍五入到原始值的最短字符串。您可以在 Python 3.1 发行说明中查看说明。在早期版本中,它只是四舍五入到小数点后 17 位。
正如他们自己警告的那样,这并不意味着它将作为十进制数字工作。
2 3 4 | 3.3000000000000003 >>> 1.1 + 2.2 == 3.3 False |
(但这应该已经敲响了你的钟声,因为比较浮点数是否相等从来都不是一件好事)
如果您想确保精确到小数位数(例如,如果您正在处理财务问题),您可以使用标准库中的模块 decimal。如果要表示小数,可以使用分数,但它们都比普通数字慢。
2 3 4 5 6 7 8 9 10 11 12 13 14 | >>> decimal.Decimal(1.1) + decimal.Decimal(2.2) Decimal('3.300000000000000266453525910') # Decimal is getting the full floating point representation, no what I type! >>> decimal.Decimal('1.1') + decimal.Decimal('2.2') Decimal('3.3') # Now it is fine. >>> decimal.Decimal('1.1') + decimal.Decimal('2.2') == 3.3 False >>> decimal.Decimal('1.1') + decimal.Decimal('2.2') == decimal.Decimal(3.3) False >>> decimal.Decimal('1.1') + decimal.Decimal('2.2') == decimal.Decimal('3.3') True |
是的,这是 Python 中的一个问题。
参见 https://docs.python.org/2/tutorial/floatingpoint.html
Haskell 不要求 Float 和 Double 是 IEEE 单精度和双精度浮点数,但它强烈推荐它。 GHC 遵循该建议。 IEEE 浮点数在所有语言中都有相同的问题。其中一些由 LIA 标准处理,但 Haskell 仅在"库"中实现。 (不,我不确定是什么库或者它是否存在。)
这个很好的答案显示了其他各种数字表示,它们要么是 Haskell 的一部分(如 Rational),要么可从 hackage 中获得,如(Fixed、CReal 和 Cyclotomic)。
Rational、Fixed 和 Cyclotomic 可能有类似的 Python 库; Fixed 有点类似于 .Net Decimal 类型。 CReal 也可能,但我认为它可能会利用 Haskell 的按需调用,并且可能难以直接移植到 Python;它也很慢。
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search
由于fast-stemmer的问题,我很难安装我想要的任何rubygem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查
我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/