我正在尝试将资金从一个“帐户”转移到另一个帐户:
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的工作原理。
另外,如果你真的很棒,请帮助我在这种特殊情况下使用它。
答案 0 :(得分:2)
首先,如果它正在使用浮点数,你也可以让它与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
始终使用Scientific Notation,因为它用于科学和金融数学中使用的精确计算。
要评论您的示例,使用SQL
肯定是正确的方法,但您必须始终使用它并相应地存储您的值。这意味着如果您写入BigDecimal
数据库,则必须使用具有正确精度的十进制格式。此外,所有实例化都必须是Float
而不是BigDecimal
的实例。如果您打算使用非常微小的裂缝或高价值进行金融数学,那么整个金融应用程序中的一个浮动可能会下雨。
为了减轻您处理金钱的一些陷阱,请查看Scientific Notation。我写它是为了使用{{1}}和ISO4217兼容实例化在ruby应用程序中表示钱。它可以帮助您在整个申请过程中处理金钱,并避免一些陷阱。
答案 1 :(得分:1)
我建议你使用这个宝石:github/RubyMoney/money
阅读更多相关信息。它开箱即用。它既使用也不浮动,也不使用BigDecimal,而只使用整数。所以根本没有精确损失。