2016-11-14 4 views
0

Я хочу написать функцию, которая вычисляет изменение при задании количества монет. Он отлично поработал, за исключением случаев, когда я действительно хочу, чтобы входные данные были Double, а не Int.«Преобразование» Двойной к Int

Это мой код

coins::[Int] 
coins = [200, 100, 50, 20, 10, 5, 2, 1] 
change::Int->[Int]->[Int] 
change n [] = [] 
change n coins 
     | n == 0 = [] 
     | n >= firstcoin = firstcoin:change (n-firstcoin) coins 
     | otherwise = change n (tail coins) 
     where firstcoin = head coins 

Это работает хорошо и все, но когда я пытаюсь изменить код, чтобы:

change::Double->[Int]->[Int] 
     | (n*100) == 0 = [] 
     | (n*100) >= firstcoin = firstcoin:change (n-firstcoin) coins 
     | otherwise = change n (tail coins) 
     where firstcoin = head coins 

происходит следующее:

[1 of 1] Compiling Main    (coin.hs, interpreted) 

    coin.hs:7:27: 
    Couldn't match expected type ‘Double’ with actual type ‘Int’ 
    In the second argument of ‘(>=)’, namely ‘firstcoin’ 
    In the expression: (n * 100) >= firstcoin 

    coin.hs:7:59: 
    Couldn't match expected type ‘Double’ with actual type ‘Int’ 
    In the second argument of ‘(-)’, namely ‘firstcoin’ 
    In the first argument of ‘change’, namely ‘(n - firstcoin)’ 
    Failed, modules loaded: none. 

Это например, используя «/», где я должен использовать fromIntegral заранее? Если да, то как это переводится здесь?

* Немного сторона вопрос: как я могу сделать список монет, написанных здесь «вкладывается» в функцию так, что подпись будет выглядеть следующим образом:

change::Int->[Int] 

(другими словами, я не хочу явно написать в списке, чтобы он работал. Мне нужно было бы изменить весь код?)

+3

Одним из первых правил обращения с валютой является не использование значений с плавающей запятой для представления суммы денег. – chepner

+0

Не могли бы вы рассказать? Я не понимаю. – Rad

+3

Значения с плавающей запятой - это просто аппроксимации действительных чисел. Вы бы не делали изменений для некоторой нечеткой доли доллара; вы делаете изменения для точного целого числа центов. – chepner

ответ

3

На этот раз я думаю, что вы ищете round. Кроме того, я думаю, что вам действительно нужна новая функция changeDouble здесь, а не для изменения change. Это позволит решить вашу проблему Double красиво и предлагает более простой подписи changeDouble :: Double -> [Int].

changeDouble :: Double -> [Int] 
changeDouble n = change (round (100 * n)) coins 

Проблема смешивания Double и Int действительно так же, как вы столкнулись бы с помощью использования / на Int с.


Как примечание стороны, даже если ваш предложили обновленный код change откомпилирует, обратите внимание, что рекурсивный вызов необходимо будет обновляться, чтобы пройти в n - (fromIntegral firstCoin)/10 вместо просто n - firstCoin.

+0

Я переименовал свою оригинальную функцию в changeHelp и ваше предложение изменить, теперь он отлично работает! Спасибо. – Rad

Смежные вопросы