Ruby 输出数字到小数点后两位
Ruby output numbers to 2 decimal places
我在将我的 ruby 对象序列化为 json 时遇到问题,更具体地说是数字格式。
我写了一个 rspec 测试来更准确地说明我的问题。
expected = '{ "foo": 1.00, "bar": 4.50, "abc": 0.00, "xyz": 1.23 }'
it 'serializes as expected' do
my_hash = { "foo": 1, "bar": 4.5, "abc": 0, "xyz": 1.23}
expect(my_to_json_method(my_hash)).to eq expected
end
这就是我遇到的问题。我可以使用 sprintf 但如何获得如上例所示的字符串输出?
用户 Sprintf
sprintf('%.2f', 5.5)
然后简单地插入到您的 JSON 作为 ERB 模板。
您可以使用 sprintf
并且可以通过提及 %.(number)f
.
来取任意多的小数点
例如:对于两位小数,%.2f
这是一个真正的实现,
2.2.2 :019 > test = { "foo": (sprintf "%.2f","1.11"), "bar": (sprintf "%.2f","4.55"), "abc": (sprintf "%.2f","0.2") }
=> {:foo=>"1.11", :bar=>"4.55", :abc=>"0.20"}
puts '{' << my_hash.map { |k, v| %Q|"#{k}": #{"%.2f" % v}| }.join(', ') << '}'
#⇒ {"foo": 1.00, "bar": 4.50, "abc": 0.00, "xyz": 1.23}
首先,您不应该使用浮点数来表示货币值。因此,让我们使用更合适的类型:(还有 Ruby Money gem)
require 'bigdecimal'
my_hash = {
foo: BigDecimal.new('1.00'),
bar: BigDecimal.new('4.50'),
abc: BigDecimal.new('0.00'),
xyz: BigDecimal.new('1.23')
}
有多种表示货币价值的选项。根据 JSON 规范,以下所有 JSON 字符串都是有效的,并且都需要在解析时进行特殊处理。由你来选择最合适的。
Note: I'm implementing a custom to_json
method to convert the BigDecimal
instances to JSON using Ruby's default JSON library. This is just for demonstration purposes, you should generally not patch core (or stdlib) classes.
1。固定精度的数字
这就是你要的。请注意,许多 JSON 库默认会将这些数字解析为浮点值。
class BigDecimal
def to_json(*)
'%.2f' % self
end
end
puts my_hash.to_json
输出:
{"foo":1.00,"bar":4.50,"abc":0.00,"xyz":1.23}
2。数字作为字符串
这适用于所有 JSON 库,但我认为将数字存储为字符串不太合适。
class BigDecimal
def to_json(*)
'"%.2f"' % self
end
end
puts my_hash.to_json
输出:
{"foo":"1.00","bar":"4.50","abc":"0.00","xyz":"1.23"}
3。整数形式的数字
您无需将货币值表示为小数,只需将 美分 输出为整数即可。这是我经常做的。
class BigDecimal
def to_json(*)
(self * 100).to_i.to_s
end
end
puts my_hash.to_json
输出:
{"foo":100,"bar":450,"abc":0,"xyz":123}
我在将我的 ruby 对象序列化为 json 时遇到问题,更具体地说是数字格式。 我写了一个 rspec 测试来更准确地说明我的问题。
expected = '{ "foo": 1.00, "bar": 4.50, "abc": 0.00, "xyz": 1.23 }'
it 'serializes as expected' do
my_hash = { "foo": 1, "bar": 4.5, "abc": 0, "xyz": 1.23}
expect(my_to_json_method(my_hash)).to eq expected
end
这就是我遇到的问题。我可以使用 sprintf 但如何获得如上例所示的字符串输出?
用户 Sprintf
sprintf('%.2f', 5.5)
然后简单地插入到您的 JSON 作为 ERB 模板。
您可以使用 sprintf
并且可以通过提及 %.(number)f
.
例如:对于两位小数,%.2f
这是一个真正的实现,
2.2.2 :019 > test = { "foo": (sprintf "%.2f","1.11"), "bar": (sprintf "%.2f","4.55"), "abc": (sprintf "%.2f","0.2") }
=> {:foo=>"1.11", :bar=>"4.55", :abc=>"0.20"}
puts '{' << my_hash.map { |k, v| %Q|"#{k}": #{"%.2f" % v}| }.join(', ') << '}'
#⇒ {"foo": 1.00, "bar": 4.50, "abc": 0.00, "xyz": 1.23}
首先,您不应该使用浮点数来表示货币值。因此,让我们使用更合适的类型:(还有 Ruby Money gem)
require 'bigdecimal'
my_hash = {
foo: BigDecimal.new('1.00'),
bar: BigDecimal.new('4.50'),
abc: BigDecimal.new('0.00'),
xyz: BigDecimal.new('1.23')
}
有多种表示货币价值的选项。根据 JSON 规范,以下所有 JSON 字符串都是有效的,并且都需要在解析时进行特殊处理。由你来选择最合适的。
Note: I'm implementing a custom
to_json
method to convert theBigDecimal
instances to JSON using Ruby's default JSON library. This is just for demonstration purposes, you should generally not patch core (or stdlib) classes.
1。固定精度的数字
这就是你要的。请注意,许多 JSON 库默认会将这些数字解析为浮点值。
class BigDecimal
def to_json(*)
'%.2f' % self
end
end
puts my_hash.to_json
输出:
{"foo":1.00,"bar":4.50,"abc":0.00,"xyz":1.23}
2。数字作为字符串
这适用于所有 JSON 库,但我认为将数字存储为字符串不太合适。
class BigDecimal
def to_json(*)
'"%.2f"' % self
end
end
puts my_hash.to_json
输出:
{"foo":"1.00","bar":"4.50","abc":"0.00","xyz":"1.23"}
3。整数形式的数字
您无需将货币值表示为小数,只需将 美分 输出为整数即可。这是我经常做的。
class BigDecimal
def to_json(*)
(self * 100).to_i.to_s
end
end
puts my_hash.to_json
输出:
{"foo":100,"bar":450,"abc":0,"xyz":123}