Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

int conversion -- gives me weird numbers

Tags:

c++

I'm new to the programming world and C++ is already losing me. I had these lines in my program

pennies=(amount-nickels*.05)/.01;

amount is a double, while and nickels are int.

The program returns the right value when pennies is a double but things are a little off (off by 1 most of the time) whenever pennies is an int.

Why is this happening?

like image 794
user2655730 Avatar asked Aug 06 '13 07:08

user2655730


2 Answers

This is happening because the value is truncated thus losing the decimal precision.

For integers:

int i;
i = 1.1  //stores 1 in i
i = 1.2  //stores 1 in i
i = 1.3  //stores 1 in i
i = 1.4  //stores 1 in i
i = 1.5  //stores 1 in i
i = 1.6  //stores 1 in i
i = 1.7  //stores 1 in i
i = 1.8  //stores 1 in i
i = 1.9  //stores 1 in i
i = 1.999999 //stores 1 in i

I would suggest you to change your expression to:

pennies=amount*100-nickels*5;
like image 134
Saksham Avatar answered Sep 28 '22 20:09

Saksham


As others have pointed out, the problem is because 0.1 and 0.05 don't have an exact representations in machine floating point. The simplest solution here is to simply round the results, instead of truncating:

pennies = round( (amount - nickels * 0.05) / 0.01 );

A better solution in this particular case (where you are dealing with coins) is simply to use integers everywhere, and do everything in terms of cents, rather than dollars. This stops working (or requires some very complex programming) very quickly however: even things like calculating VAT or sales tax cause problems. For such cases, there are two possible solutions:

  • Continue using double, rounding as necessary. This is the simplest and most general solution. Be aware, however, that when using it, rounding is done on binary values, and it may in some cases differ from what you would get with rounding decimal values. The difference should be small enough that it won't matter for every day use, but most countries have laws specifying how such values must be rounded, and those rounding rules are always specified in decimal. Which means that this solution cannot be used in cases where legal requirements hold (e.g calculating sales tax, corporate bookkeeping, etc.).

  • Use some sort of decimal class. There are a number available on the network. This will result in slower execution times. (Typically, who cares. You'll get the results in 100 microseconds, rather than 10. But there are exceptions; e.g. when doing Monte Carlo simulations.)

Also, you must be aware when large values are involved. For your personal finances, it's almost certainly irrelevant, but int does have a maximum value, and there is a point where double can no longer represent integer values correctly.

Of course, if this is just an exercise to help in learning C++, just use round or integers, and don't worry too much about the rest.

And as for your comment "C++ is already losing me": this has nothing to do with C++ per se. You'd encounter exactly the same issues in (almost) any programming language.

like image 36
James Kanze Avatar answered Sep 28 '22 21:09

James Kanze