首页 > 解决方案 > 将字符串货币转换为使用 ruby​​ 浮动

问题描述

我有以下字符串:

“1.273,08”

我需要转换为浮点数,结果必须是:

1273.08

我尝试了一些使用 gsub 的代码,但我无法解决这个问题。我该如何进行这种转换?

标签: ruby

解决方案


您已经收到了两个很好的答案,如何使用和将您按摩String成您想要的格式。String#deleteString#tr

但还有一个更深层次的问题。

十进制值 1 273.08 10 无法准确表示为 IEEE 754-2019 / ISO/IEC 60559:2020 binary64浮点值。

就像值 1/3rd 可以很容易地以三进制 (0.1 3 ) 表示,但在十进制中具有无限表示 (0.33333333...<sub>10,即 0.[3]...<sub>10),因此无法准确表示, 值 8/100 可以很容易地用十进制 (0.08 10 ) 表示,但在二进制中具有无限表示 (0.0001010001111010111000010100011110101110000101...<sub>2, 即 0.[00010100011110101110]...<sub>2)。换句话说,不可能将 1 273.08 10表示为 Ruby Float

这不是特定于 Ruby,甚至不是编程,这只是基本的高中数学:你不能用二进制表示这个数字,点,就像你不能用十进制表示 1/3 或任何整数基数的 π。

当然,计算机没有无限的内存,所以 1 273.08 10不仅在二进制中有无限表示,而且作为 a Float,在 64 位之后也会被截断。作为 IEEE 754-2019 / ISO/IEC 60559:2020 binary64浮点值,最接近 1 273.08 10的可能值为 1 273.079 999 999 999 927 240 423 858 17 10小于1 273.08 10

这就是为什么你永远不应该使用二进制数字来表示货币:每个人都会期望它是十进制的,而不是二进制的;如果我写一张支票,我用十进制写,而不是二进制。人们会期望代表 1/3 美元是不可能的,他们会期望代表 π 美元是不可能的,但是他们不会期望也不会接受如果他们将 1273.08 美元存入他们的账户,他们实际上最终会得到略低于那个。

表示金钱的正确方法是使用专门的Money数据类型,或者至少使用bigdecimal标准库中的库:

require 'bigdecimal'

BigDecimal('1.273,08'.delete('.').tr(',', '.'))
#=> 0.127308e4

推荐阅读