为什么Ruby的Rational类不同于数字参数处理字符串参数?

时间:2015-05-28 19:01:48

标签: ruby aspect-ratio rational-number

我正在使用ruby的Rational库来转换宽度和宽度。图像高度与宽高比。

我注意到字符串参数的处理方式与数字参数不同。

>> Rational('1.91','1')
=> (191/100)
>> Rational(1.91,1)
=> (8601875288277647/4503599627370496)

>> RUBY_VERSION
=> "2.1.5"
>> RUBY_ENGINE
=> "ruby"

仅供参考1.91:1是Facebook推荐用于其平台上图像的宽高比。

191和100之类的值比8601875288277647和4503599627370496更方便存储在我的数据库中。但我想在决定使用哪种方法之前了解这种不同的来源。

The Rational test suite似乎没有涵盖这个确切的案例。

2 个答案:

答案 0 :(得分:1)

Float 1.91存储为double,具有给定的精度,受二进制显示的限制。等效的Rational对象尽可能保留这种精度,因此它是巨大的。没有办法将1.91精确地存储在一个double中,但是你得到的值足够接近大多数用途。

对于String,它表示一个不同的值 - 确切的值为1.91 - 并且当您创建Rational时,它会更好地保留它。它比Float更正确,UT用于计算需要更长的时间。

这类似于1.0 / 3的问题,因为它“永远持续”0.333333 ......等等,但Rational可以完全代表它。

答案 1 :(得分:1)

免责声明:这只是一个有根据的猜测,基于如何实现这一壮举的一些知识。

正如Kent Dahl所说,Floats不精确,它们有一个固定的精度,这意味着1.91真的是1.910000000000000000001或类似的东西,ruby“知道”应该显示为1.91。

“1.91”另一方面是一个字符串,基本上是一个字符数组:'1','。','9','1'。

这就是说,你需要做的就是建立浮动的理性:

  1. 摆脱了。 (数学上将分子和分母乘以10 ^ x,或乘以十次,因为后面有数字。)
  2. 找出最大的共同点(gcd)
  3. 用gcd
  4. 除以num和denom

    然而,步骤1与Float和String有点不同:

    • Float,我们将不得不乘以10 ^ x,其中x是(因为精度)不是2(正如人们认为的那样是1.91),但更像是16(记住:1.9100 ...... 1)
    • 对于String,我们可以将它转换为浮点数并执行相同的技巧,但是,嘿,有一种更简单的方法:我们只计算点后面的字符数(即2),删除点并乘以带有10 ^ 2的denom ......这不仅更简单,而且更精确。

    当应用第3步时,大数字可能会再次消失,这就是为什么在处理浮点数的理性时你不会总是得到那些奇怪的结果。

    TLDR:根据String或FLoat的参数,数字的构建方式会有所不同。 FLoats可以产生长屁股,因为精确度。