David Puc
David Puc

Reputation: 1

Code for calculating amount of currency thinks it’s quirky. (Unintended Decimals keep appearing)

I’m just starting out learning C# through CodeAcademy. I’m supposed to write a program to calculate the least amount of “coins” of different values that are needed to reach a specified amount. It all went fine while following the instructions, but at the end of the exercise you are encouraged to write some more code to make the program work with decimal inputs (instead of just whole numbers).

I essentially copied the same code used for the complete amounts with slight modifications (multiplying the initial amount by 100) so that it could still run and give the required results. However, the last value (bronze cents) keeps giving me numbers with decimals for some reason. I thought about using Math.Floor() but after a few trials I realized it isn’t always an excess. Can anyone provide some help? Are there any inherent limits to the Math.Floor() command that I should have been aware of? Did I just do a big dumb?

tl;dr: noob coder here, wondering why code not do what i want it to do

using System;

namespace MoneyMaker
 {
class MainClass
{
public static void Main(string[] args)
{
  // This code is meant to divide an (user given) amount of money into coins of different values.

  // First we ask for an input.
  Console.WriteLine("Welcome to Money Maker!.00");
  Console.WriteLine("Please enter the amount you want to divide in Coins:");
  string strAmount = Console.ReadLine();
  Console.WriteLine($"${strAmount} Canopy is equal to:");
  double wholeAmount = Convert.ToDouble(strAmount);

  // These are the values of each coin.
  // The cents are multiplied by 100 for the purposes of using then in the code.
  // The bronze coins are listed, but unused, since their value is essentially 1.
  double gold = 10;
  double silver = 5;
  //double bronze = 1;
  double smolGold = .1 * 100;
  double smolSilver = .05 * 100;
  //double smolBronze = .01 * 100;

  // These lines calculate the integral values (gold, silver and bronze coins).
  double douAmount = Math.Floor(wholeAmount);
  double goldCoins = Math.Floor(douAmount / gold);
  double silAmount = douAmount % gold;
  double silverCoins = Math.Floor(silAmount / silver);
  double bronzeCoins = silAmount % silver;

  // These lines calculate the decimal values (gold, silver and bronze cents).
  // They start by multiplying the cents by 100, rendering the rest of the lines the same as in the integral values.
  double smolAmount = 100 * (wholeAmount - douAmount);
  double goldCents = Math.Floor(smolAmount / smolGold);
  double littleSilver = smolAmount % smolGold;
  double silverCents = Math.Floor(littleSilver / smolSilver);
  //ERROR: There seems to be an issue with the bronze cents, returning a value with decimals.
  double bronzeCents = littleSilver % smolSilver;

  // Finally, the output string with the results:
  Console.WriteLine($"\n Gold Coins: {goldCoins} \n Silver Coins: {silverCoins} \n Bronze Coins: {bronzeCoins} \n Gold Cents: {goldCents} \n Silver Cents: {silverCents} \n Bronze Cents: {bronzeCents}");
}

} }

Upvotes: 0

Views: 420

Answers (1)

Eric Lippert
Eric Lippert

Reputation: 660297

Never use doubles for currency. Use decimal.

Use double when representing a physical quantity, like length, mass, speed, and so on, where insignificant representation errors do not matter. Use decimal to represent money, where every penny or fraction of a penny matters.

The difference is: double represents numbers as a fraction where the denominator is a power of two, like "5/32nds". decimal represents numbers as a fraction where the denominator is a power of ten, like "3/100ths". The former will tend to accumulate representation errors for fractions like "3/100ths", but the latter will not.

If your tutorial is suggesting that you use double arithmetic for computations involving money, get a better tutorial.

All that said, I suspect you may misunderstand what the % operator is for if you are using it on non-integer quantities. It is primarily for use on integer quantities, so if you're using it on decimals or doubles, something strange is probably going on.

Upvotes: 2

Related Questions