微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ruby-on-rails – Ruby浮点数学 – Sum Calc中的精度问题

大家早上好,

我在浮点数学方面遇到了一些问题,并且在“.to_f”,“* 100”和“.0”中完全丢失了!

我希望有人可以帮我解决我的具体问题,并解释为什么他们的解决方案有效,以便我下次理解这一点.

我的程序需要做两件事:

>求和小数列表,确定它们是否总和为1.0
>确定1.0和数字之和之间的差异 – 将变量的值设置为精确差值,使总和等于1.0.

例如:

> [0.28,0.55,0.17] – >应该总和为1.0,但我一直得到1.xxxxxx.我正在以下列方式实现总和:

sum = array.inject(0.0){|sum,x| sum+ (x*100)} / 100

>我需要这个功能的原因是我正在读取一组来自excel的小数.它们不是100%精确(它们缺少一些小数点)所以总和通常来自0.999999xxxxx或1.000xxxxx.例如,我将获得如下值:

0.568887955,0.070564759,0.360547286

为了解决这个问题,我可以得到前n-1个数字的总和,然后稍微改变最终数字,以便所有数字总和为1.0(必须使用上面的等式,或者我最终得到的任何数字进行验证) ).我目前正在实现如下:

sum = 0.0
          array.each do |item|
            sum += item * 100.0
          end
          array[i] = (100 - sum.round)/100.0

我知道我可以通过注射来做到这一点,但是试图用它来看看它有什么用.我认为这通常是有效的(从检查输出),但它并不总是符合上面的验证总和.所以,如果需要,我也可以调整这个.请注意,我在这些数字中只需要两个小数精度 – 即0.56而不是0.5623225.我可以在演示时或者在计算期间将它们围绕下来……对我来说无关紧要.

非常感谢您的帮助!

解决方法

如果准确性对您很重要,则不应使用浮点值,根据定义,浮点值不准确. Ruby有一些精确的数据类型,用于进行精度很重要的算术运算.根据您实际需要计算的内容,它们在我的头顶上是 BigDecimal,RationalComplex.

看起来在你的情况下,你正在寻找的是BigDecimal,它基本上是一个具有固定位数的数字,其中小数点后面有一个固定的位数(与浮点相反,小数点后面有任意位数).

当您从Excel中读取并故意将这些字符串(如“0.9987”)转换为浮点时,您将立即丢失字符串中包含的准确值.

require "bigdecimal"
BigDecimal("0.9987")

这个价值是准确的.它是0.9987.不是0.998732109,或任何接近它的东西,但是0.9987.您可以对其使用所有常用的算术运算.如果不将浮点混合到算术运算中,则返回值将保持精确.

如果你的数组包含你从Excel得到的原始字符串(即你没有#to_f’d它们),那么这将给你一个BigDecimal,它是它们之和和1的差值.

1 - array.map{|v| BigDecimal(v)}.reduce(:+)

原文地址:https://www.jb51.cc/ruby/264640.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐