2

我正在使用 ruby​​ 的 Rational 库将图像的宽度和高度转换为纵横比。

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

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

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

FYI 1.91:1 是 Facebook 为其平台上的图像推荐的宽高比。

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

Rational 测试套件似乎没有涵盖这个确切的情况。

4

2 回答 2

1

Float 1.91 存储为具有给定精度的双精度,受二进制表示的限制。等价的 Rational 对象尽可能地保留了这种精度,因此它是巨大的。无法将 1.91 精确地存储在双精度数中,但是您获得的值对于大多数用途来说已经足够接近了。

至于字符串,它代表一个不同的值 - 1.91 的确切值 - 当您创建一个 Rational 时,它会更好地保留它。它比 Float 更正确,UT 用于计算需要更长的时间。

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

于 2015-05-28T20:24:21.737 回答
1

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

正如 Kent Dahl 已经说过的那样,浮点数并不精确,它们具有固定的精度,这意味着 1.91 实际上是 1.910000000000000000001 或类似的东西,红宝石“知道”应该显示为 1.91。

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

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

  1. 摆脱 . (在数学上,分子和分母乘以 10^x,或乘以 10 的倍数,因为后面有数字。)
  2. 求最大公分母 (gcd)
  3. 用 gcd 将 num 和 denom 分开

然而,第 1 步对于 Float 和 String 有点不同:

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

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

TLDR:数字将根据 String 或 Float 的参数构建不同。Floats 可以产生很长的数字,因为精度。

于 2015-05-28T21:26:52.297 回答