Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Truncate a decimal value in C++

What's the easiest way to truncate a C++ float variable that has a value of 0.6000002 to a value of 0.6000 and store it back in the variable?

like image 581
BeachRunnerFred Avatar asked Nov 20 '08 00:11

BeachRunnerFred


5 Answers

Use this:

floor(0.6000002*10000)/10000
like image 120
JBOI Avatar answered Sep 25 '22 02:09

JBOI


Similar to other answers, BUT you must not forget that round, floor and trunc are different by definition. See the definition and output example of the following:

http://www.cplusplus.com/reference/cmath/trunc/

In this case we need to trucate with a precision of 4 decimals and get rid of non-significant decimals:

trunc(valueToTrunc*10000)/10000

or

value = (double)((int)(valueToTrunc*10000))/(double)10000
like image 43
Rubarb Avatar answered Sep 23 '22 02:09

Rubarb


Realistically that's not possible. It's not a C++ limitation, but just the way floating point works. For many values there are no precise representations, so you can't simply truncate to a number of digits.

You could truncate when printing using printf format strings.

If you really need to be able to store only a limited number of digits, I suggest you use a fixed-precision data type instead.

like image 7
Kamil Kisiel Avatar answered Nov 07 '22 19:11

Kamil Kisiel


A good reference for why this happens can be found in What Every Computer Scientist Should Know About Floating Point Arithmetic by David Goldberg.

like image 12
Greg Hewgill Avatar answered Nov 07 '22 17:11

Greg Hewgill


First it is important to know that floating point numbers are approximated. See the link provided by @Greg Hewgill to understand why this problem is not fully solvable.

But here are a couple of solutions to the problem that will probably meet your need:

Probably the better method but less efficient:

char sz[64];
double lf = 0.600000002;
sprintf(sz, "%.4lf\n", lf); //sz contains 0.6000

double lf2 = atof(sz);

//lf == 0.600000002;
//lf2 == 0.6000

printf("%.4lf", lf2); //print 0.6000

The more efficient way, but probably less precise:

double lf = 0.600000002;
int iSigned = lf > 0? 1: -1;
unsigned int uiTemp = (lf*pow(10, 4)) * iSigned; //Note I'm using unsigned int so that I can increase the precision of the truncate
lf = (((double)uiTemp)/pow(10,4) * iSigned);
like image 9
Brian R. Bondy Avatar answered Nov 07 '22 19:11

Brian R. Bondy