我正在尝试将钱从一个"帐户"转移到另一个"帐户":
puts ("nTransfer how much?")
require 'bigdecimal'
amount = gets.chomp
amount = BigDecimal(amount) #<--Does BigDecimal have to work with strings???
puts ("nTransfer to which account?")
acct_to = gets.chomp.to_i #<--Accounts are numbered previously for the user.
acct_to = acct_to - 1 #<--Since the account numbers are stored in an array...
#having a problem with #{amount} in the string below. It is showing something like
#1.2E0???
puts ("nTransfer #{amount} from #{names[acct_from]} to #{names[acct_to]}? [1 - yes] / [2 - no]")
#Makes transfer==============================
e = gets.chomp.to_i
if e == 1
puts ("nTransferring!")
sum1 = 0
sum2 = 0
sum1 = BigDecimal(ac[names[acct_from]].to_s) #<-- ac is a hash
sum2 = BigDecimal(ac[names[acct_to]].to_s)
ac[names[acct_from]] = sum1 - amount
ac[names[acct_to]] = sum2 + amount
puts ("n#{names[acct_from]}'s new balance is #{ac[names[acct_from]]}.")
puts ("n#{names[acct_to]}'s new balance is #{ac[names[acct_to]]}.")
end
end
好的,我有一个非常好的工作,数字作为浮点数运行;但是,如你所知,浮点数会导致问题。
请帮助我介绍一下 bigdecimal 的工作原理。
另外,如果你真的很棒,请帮助我让它在这种特定情况下工作。
首先,如果它与浮点数一起工作,你也可以让它与BigDecimal
一起工作,而且你应该这样做,因为显而易见的原因。
因此,在代码注释中回答您的第一个问题:是的,BigDecimal
实例化必须处理字符串,原因很明显:字符串化数字值不容易出现任何不准确,并且不共享浮点表示的限制:
# Think of this number
float = 23.12323423142342348273498721348923748712340982137490823714089374
# Ruby will truncate its precision to 17, because Float's are not made for precise, but for fast calculation
float #=> 23.123234231423424
# Now, if BigDecimal would initialize with a float value, the precision would get lost on the way, too. Therefore, BigDecimal needs strings
big_decimal_from_float = BigDecimal.new(23.12323423142342348273498721348923748712340982137490823714089374.to_s)
big_decimal_from_string = BigDecimal.new("23.12323423142342348273498721348923748712340982137490823714089374")
# Now you'll see that the BigDecimal initialized "with a float value" will have lost some precision
回答你的第二个问题,1.2E0
只是1.2
的科学记数法。 BigDecimal
总是使用科学记数法,因为它旨在用于科学和金融数学中使用的真正精确的计算。
要评论您的示例,使用 BigDecimal
肯定是正确的方法,但您必须始终使用它并相应地存储您的值。这意味着,如果写入SQL
数据库,则必须使用具有正确精度的十进制格式。此外,其中的所有实例化都必须是BigDecimal
的实例,并且永远不会Float
。如果您打算用非常小的裂缝或高值进行金融数学,则整个金融应用程序中的一辆花车可能会在您的游行中下雨。
为了减轻您处理金钱的一些陷阱,请查看Exchange
宝石。我编写它是为了有一种使用 BigDecimal
和ISO4217兼容实例在 ruby 应用程序中表示货币的方法。它可以帮助您在整个申请过程中处理资金并避免所涉及的一些陷阱。
我建议你使用这个gem:github/RubyMoney/money
阅读更多关于它的信息。它是开箱即用的。它既不使用浮点数,也不使用BigDecimal,而只是整数。所以完全没有精度损失。