2016-12-03 2 views
-1

Я пишу простую функцию для вычисления стоимости мешка с монетами. Он потребляет четыре цифры: количество пенни, никеля, копейки и четверти в сумке; он производит сумму денег в сумке.Неправильный расчет с использованием типа Scala Int и Double

Вот функция:

scala> def sum_coins(penny:Int=0, nickel:Int=0, dime:Int=0, quarter:Int=0) = { penny * (0.01) + nickel * 0.05 + dime * 0.1 + quarter * 0.25 } 

Почему результат выглядит так?

scala> sum_coins(1,1,1,1) 
res13: Double = 0.41000000000000003 

Я ожидаю, что результат должен быть 0,41

+0

'0.01',' 0.05', '0.1',' 0.25' литералы 'Double' по умолчанию, используйте' Decimal' вместо –

+2

Возможный дубликат (HTTP [Является плавающей точкой математике сломана?]://stackoverflow.com/questions/588004/is-floating-point-math-broken) –

ответ

0

литералов 0.01, 0.05, 0.1, 0.25 с плавающей точкой Double по умолчанию, вы должны использовать вместо BigDecimal. В следующей реализации вместо этого используется BigDecimal.

trait Money{ 
    def amount:BigDecimal 
} 
case class Dollar(override val amount: BigDecimal) extends Money{ 
    def +(d:Dollar):Dollar = Dollar(this.amount + d.amount) 
} 
case class Penny(override val amount: BigDecimal) extends Money 
case class Nickel(override val amount: BigDecimal) extends Money 
case class Dime(override val amount: BigDecimal) extends Money 
case class Quarter(override val amount: BigDecimal) extends Money 

implicit def pennyToDollar(p: Penny):Dollar = Dollar(p.amount * BigDecimal(0.01)) 
implicit def nickelToDollar(n: Nickel):Dollar = Dollar(n.amount * BigDecimal(0.05)) 
implicit def dimeToDollar(d: Dime):Dollar = Dollar(d.amount * BigDecimal(0.1)) 
implicit def quarterToDollar(q: Quarter):Dollar = Dollar(q.amount * BigDecimal(0.25)) 


def sumCoins(penny:Int=0, nickel:Int=0, dime:Int=0, quarter:Int=0):Dollar = { 
    Penny(penny) + Nickel(nickel) + Dime(dime) + Quarter(quarter) 
} 

sumCoins(1,1,1,1) //Dollar(0.41) 
0

Это тривиальный двойной "проблема"

Для точных цифр, как и деньги, используйте BigDecimal, а предложить г-D.

def sum_coins(penny:Int=0, nickel:Int=0, dime:Int=0, quarter:Int=0) = 
penny * BigDecimal(0.01) + 
nickel * BigDecimal(0.05) + 
dime * BigDecimal(0.1) + 
quarter * BigDecimal(0.25) 
+1

Альтернативный подход заключается в том, чтобы сменить единицы на центы, а не доллары. Таким образом, целая математика всегда будет правильной. –