1.8 与 1.9 中的 BigDecimal

2024-01-10

升级到 ruby​​ 1.9 时,在比较预期值与实际值时,我的测试失败了BigDecimal这是 Float 除法的结果。



expected: '0.495E0',9(18)
got:      '0.4950000000 0000005E0',18(27)
  

谷歌搜索“bigdecimal ruby​​ precision”和“bigdecimalchanges ruby​​ 1.9”之类的东西并没有给我带来任何帮助。

How did BigDecimalruby 1.9 中的行为发生变化吗?

update 1

> RUBY_VERSION
=> "1.8.7"
> 1.23.to_d
=> #<BigDecimal:1034630a8,'0.123E1',18(18)>

> RUBY_VERSION
=> "1.9.3"
> 1.23.to_d
=> #<BigDecimal:1029f3988,'0.123E1',18(45)>

18(18)和18(45)是什么意思?我想象精度,但是符号/单位是什么?

update 2

代码正在运行:

((10 - 0.1) * (5.0/100)).to_d

我的测试期望它等于(==):

0.495.to_f

这在 1.8 下通过,在 1.9.2 和 1.9.3 下失败


平等比较很少能在 FP 值上取得成功


简短的回答是Float#to_d在 1.9 中更准确,并且正确地未通过 1.8.7 中不应成功的相等测试。

长答案涉及浮点编程的基本规则:从不进行相等比较。相反,模糊比较如if (abs(x-y) < epsilon)推荐,或者编写代码来完全避免相等比较的需要。

Although there are in theory about 232 single-precision numbers and 264 double-precision numbers that could be exactly compared, there are an infinite number that cannot be so compared. (Note: it is safe to do equality comparisons on FP values that happen to be integral. So, contrary to much advice, they are actually perfectly safe for loop indices and subscripts.)

更糟糕的是,我们编写小数的方式使得与任何特定常量的比较不太可能成功。

那是因为分数是二进制的,即 1/2 + 1/4 + 1/8 ...但我们的常数是十进制的。因此,例如,考虑范围内的货币金额$1.00, $1.01, $1.02 .. $1.99.此范围内有 100 个值,但其中只有 4 个具有精确的 FP 表示:1.00, 1.25, 1.50, and 1.75.

那么,回到你的问题。你的结果是0.495没有精确的表示,输入常数也没有0.1.首先计算两个不同大小的 FP 数的减法。为了完成减法,较小的数字将被非规范化,因此它将丢失两个或三个低位。结果,计算将导致比 0.495 稍大的数字,因为没有从 10 中减去整个 0.1。您的常数实际上(在内部)略小于 0.495。这就是比较失败的原因。

Ruby 1.8 一定是意外或故意丢失了一些低位,并有效地引入了舍入步骤,最终对您的测试有所帮助。

请记住:经验法则是您必须在此类舍入中显式编程以进行浮点比较。


Notes. To answer the question from the comments about simple decimal fraction constants not having exact representations: They don't have exact finite forms because they repeat in binary. Every machine fraction is a rational number of the form x/2n. Now, the constants are decimal and every decimal constant is a rational number of the form x/(2n * 5m). The 5m numbers are odd, so there isn't a 2n factor for any of them. Only when m == 0 is there a finite representation in both the binary and decimal expansion of the fraction. So, 1.25 is exact because it's 5/(22*50) but 0.1 is not because it's 1/(20*51). There is simply no way to express 0.1 as a finite sum of x/2n components.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

1.8 与 1.9 中的 BigDecimal 的相关文章

随机推荐

  • 如何为具有动态键的对象定义接口?

    我有一个像这样的对象 它是由下划线创建的 groupBy method myObject key Object Object2 Object3 key2 Object4 Object5 Object6 我如何将其定义为 TypeScript
  • 如何获取分类变量中类别的各种组合并同时对其进行聚合?

    我试图获取三列中数据的各种组合 在这样做的同时 我还想聚合 求和 这些值 我的数据如下所示 下面是我的示例输出 Dim1 Dim2 Dim3 Spend A X Z 100 A Y Z 200 B X Z 300 B Y Z 400 示例输
  • 上下文相关实例作为简单注入器中的单例

    我有一个关于ContextDependentExtensions of SimpleInjector图书馆 我们有以下扩展来添加将元素添加到具有某些上下文的注入器中的可能性 上下文相关扩展 https github com simplein
  • 实现自定义 MembershipUser 和自定义 MembershipProvider

    我尝试在我自己的数据库中使用自定义 MembershipUser 实现自定义 MembershipPriver 具有特定的用户表模型 这是完全不同的文件 iTwitterMembershipProvider cs using System
  • Chart.js 中的 Utils 包

    我正在尝试从 Chart js 文档中重现此示例 https www chartjs org docs latest samples line interpolation html https www chartjs org docs la
  • 如何从 Android 上的列表视图中删除分隔线? [复制]

    这个问题在这里已经有答案了 我正在开发一个应用程序Listview 并且列表中的项目已经具有我不需要分隔线的样式 如何将分隔线设置为隐藏或删除分隔线ListView 你可以试试android divider null
  • Python ValueError:池未在异步多处理中运行

    我有一个简单的代码 path filepath1 filepath2 filepath3 def umap embedding filepath file np genfromtxt filepath delimiter if len fi
  • 如何获取 Android 设备的物理方向(以度为单位)。

    我知道我必须使用 OrientationListener 类从设备获取角度 我想要得到 90 和90 之间的角度 我不知道该怎么做 左图 90度 中图 0度 右图 90度 Code class OrientationListener imp
  • 缺少 Microsoft 时区

    我正在考虑使用微软时区 https support microsoft com en gb help 973627 microsoft time zone index values 通过利用系统时区信息 https msdn microso
  • 如何在IDEA中使用类路径而不是模块路径运行Java 9应用程序?

    当我在 IDEA 中运行主类时 它将模块及其依赖项放在模块路径上 是否可以将其更改为类路径 如果您没有定义模块信息 IDEA 会在类路径上设置应用程序和您的依赖项 由于您有一个模块信息 它是一个显式模块 因此它必须位于模块路径上 通常 您现
  • initState 方法中的 Flutter showDialog(context)

    我正在尝试使用showDialog context builder 当用户导航到某个页面时显示问候消息 我通过调用尝试了这个showDialog in the initState该页面上有状态小部件的方法 虽然它确实有效 但我似乎无法访问实
  • 列名称无效。 [ 节点名称(如果有) = t0,列名称 = 版本 ]

    我在尝试查询时遇到问题SQLCE我的 Windows Phone Mango 应用程序中的数据库 当我执行时出现异常 foreach var item in myDataContext MyTable Select item gt item
  • golang中的windows加密rdp密码

    like http play golang org p fD7mx2k4Yc http play golang org p fD7mx2k4Yc windows rdp密码加密http www remkoweijnen nl blog 20
  • 在经典 ASP 中添加逗号的 HTML 表单值

    我有一个经典的 ASP 页面 它会提交回自身 奇怪的是 从选择返回的值的末尾添加了逗号 以前有人遇到过这样的事情吗 有推荐的故障排除步骤或工具吗 我期望值以数字形式返回 它们是选项中显示的值的 ID 我检查了页面中是否有神秘逗号 但无法找到
  • iOS UTF-8 标签字符串

    我有一个 UTF 8 编码字符串 我想在标签中显示它 当我设置断点并检查保存字符串的变量时 一切看起来都很好 但是 当我尝试输出到日志或标签时 我得到拉丁编码 我已经尝试了几乎所有关于 SO 及其他的建议 但我就是无法让字符串正确显示 这是
  • 视图左上角的 GMSMarker 图标 (iOS)

    我正在尝试创建一个包含 GMSMapView 的 UITableViewCell 其中 GMSMarker 位于当前位置的中心 问题是标记总是出现在当前位置的左上角 我不知道如何解决这个问题 我尝试按照以下步骤操作 使用 UItablevi
  • 什么是 { 得到;放; C# 中的语法?

    我正在学习 ASP NET MVC 我可以阅读英文文档 但我不太明白这段代码中发生了什么 public class Genre public string Name get set 这是什么意思 get set 它是所谓的 auto 属性
  • 更改 NSDictionary 中的键名

    我有一个方法 它返回一个带有某些键和值的 nsdictionary 我需要将字典中的键名称更改为新的键名称 但该键的值需要相同 但我被困在这里 需要帮助 此方法仅适用于可变字典 如果新密钥已经存在 它不会检查应该做什么 您可以通过调用 mu
  • 在 Visual C# 中从 RichTextBox 中删除 RichText 格式

    我正在用 C 开发一个高级富文本编辑器 但偶然发现了一个我似乎无法理解的问题 我一直试图让用户将他们的文档保存为文本文件 纯文本 通过使用以下内容 我的 RichTextBox Save 文件 文件路径 PlainText 但问题是 当他们
  • 1.8 与 1.9 中的 BigDecimal

    升级到 ruby 1 9 时 在比较预期值与实际值时 我的测试失败了BigDecimal这是 Float 除法的结果 expected 0 495E0 9 18 got 0 4950000000 0000005E0 18 27 谷歌搜索 b