Truncate a decimal value in C++

…衆ロ難τιáo~ 提交于 2019-11-27 03:28:20

问题


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?


回答1:


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);



回答2:


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




回答3:


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.




回答4:


i think the question that should be asked here is: Why do you need it truncated?

If its for comparison between values, perhaps you should consider using the epsilon test. (with an extra tolerance value, in your case, since it seems to be far larger than the generally accepted epsilon).

If you're just wanting to print it out as 0.6000 , use the methods others have suggested.




回答5:


roundf(myfloat * powf(10, numDigits)) / powf(10, numDigits);

For example, in your case you're truncating three digits (numDigits). You'd use:

roundf(0.6000002 * 1000) / 1000
// And thus:
roundf(600.0002) / 1000
600 / 1000
0.6

(You'd probably store the result of powf somewhere, since you're using it twice.)

Due to how floats are normally stored on computers, there'd probably be inaccuracies. That's what you get for using floats, though.




回答6:


Use this:

floor(0.6000002*10000)/10000



回答7:


For C++11 you can use std::round defined in header <cmath>:

auto trunc_value = std::round(value_to_trunc * 10000) / 10000;



回答8:


Here is a function using the advice in other answers and an example of its use:

#include <iostream>
#include <cmath>

static void Truncate(double& d, unsigned int numberOfDecimalsToKeep);

int main(int, char*[])
{

  double a = 1.23456789;
  unsigned int numDigits = 3;

  std::cout << a << std::endl;

  Truncate(a,3);

  std::cout << a << std::endl;

  return 0;
}

void Truncate(double& d, unsigned int numberOfDecimalsToKeep)
{
    d = roundf(d * powf(10, numberOfDecimalsToKeep)) / powf(10, numberOfDecimalsToKeep);
}



回答9:


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


来源:https://stackoverflow.com/questions/304011/truncate-a-decimal-value-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!