-2

I am working on a homework assignment where I need to convert money in the form of a float to an int.

I know I could multiply the float by 100 and convert it into (cast?) an int. On the walk through for this problem set though, they talked about the need to round. I understand that .1 can't be represented accuratly as a float. None of the explanations I've read about rounding in c seem to solve my problem though. Obviously I'm confused. Could someone please explain or at least point me in the right direction? Thanks!

  • 1
    What do you want to know? How is the currency defined? – Gilian Joosen Aug 18 '15 at 14:14
  • 3
    Perhaps [Why not use Double or Float to represent currency?](http://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency?rq=1) – Bo Persson Aug 18 '15 at 14:15
  • 1
    A cast will always truncate (round down) toward zero. The floor() function (defined in "math.h") will always round down toward negative infinity. For rounding to closest integer, try adding 0.5 to your positive float value, then cast to int. Negative values need to be treated differently. Be very careful about negative values and rounding rules. Test every case you can think of. – ChisholmKyle Aug 18 '15 at 14:18
  • @ChisholmKyle Note: `(int) (pos_float + 0.5)` also fails for the `float` just smaller than `0.5` and for many of the `float` near the range when the [ULP](https://en.wikipedia.org/wiki/Unit_in_the_last_place) is 1 or 0.5. – chux - Reinstate Monica Aug 18 '15 at 14:48
  • I guess I don't understand why exactly I'm rounding in this case (only trying to change positive dollars.cents to cents). Won't multiplying 1.10*100 and then casting that as an integer always work? I understand the basic concept of why floats are always accurate, but why do I need to do any rounding here? – shannon4455 Aug 18 '15 at 15:50
  • 1
    Thanks for the tip chux. @shannon4455 what about fractions of cents? A bank or large company can lose lots of money when balancing budgets if they don't properly round to the nearest cent. It might be a good exercise to write your own round() function to learn about casts and floating point precision. Side note: watch "Office Space" – ChisholmKyle Aug 18 '15 at 17:48
  • @shannon4455, no multiplying by 100 and casting the result to `int` will *not* always produce a result rounded to the nearest integer. In fact, it will be off by 1 for half of all possible inputs -- those whose fractional parts are greater than 0.5. Whether it does the right thing where the fractional part is exactly equal to 0.5 depends on what rounding mode you want. First adding 0.5 as @chux suggested will produce a correctly rounded result in almost all cases, subject to the caveats that @chux also provided. – John Bollinger Aug 18 '15 at 18:00
  • You might consider multiplying by 100 and then applying a rounding function such as `round()`, `rint()`, or `nearbyint()` before converting to `int`. – John Bollinger Aug 18 '15 at 18:05
  • @shannon4455, float is NOT always accurate. Infact float cannot exactly represent many numbers. This is why, in the real world, in finance, it is not used except for printing numbers. – user3629249 Aug 18 '15 at 22:41
  • Does this answer your question? [Why not use Double or Float to represent currency?](https://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency) – wovano Dec 22 '22 at 11:20

1 Answers1

0

To convert a float to an int assuming it represents money in hundredths:

First cut:

#include <math.h>
int ConvertMoney(float dollar) {
  int cent = (int) roundf(dollar * 100.0f);
}

Works OK, but has problems when:
1) dollar is not in the range INT_MIN <= dollar * 100 <= INT_MAX
2) dollar * 100.0f is near half-way between two whole numbers.

So let us cheat and use double. Now the calling code can test for conversion success. This solves problem #1 and greatly reduces, though not eliminates, problem #2. The logic of the range test is written is such a way to handle NaNs.

#include <stdbool.h>
#include <math.h>

// false on success, else return true
bool ConvertMoney(float dollar, int *cent) {
  double cent2 = round(dollar*100.0);
  if (cent2 >= INT_MIN && cent2 <= INT_MAX) {
    *cent = (int) cent2;
    return false; 
  }
  return true;
}

A third version would get into deeper details - which I think is further than what OP wants now.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256