views:

115

answers:

4

Hello, I would like to truncate the float to 4 digits. Are there some efficient way to do that? My current solution is:

double roundDBL(double d,unsigned int p=4)
{
 unsigned int fac=pow(10,p);
 double facinv=1.0/static_cast<double>(fac);
 double x=static_cast<unsigned int>(d*fac)*facinv;
 return x;
}

but using pow and delete seems to me not so efficient.

kind regards

Arman.

+2  A: 

Efficiency depends on your platform.

Whatever methods you try, you should profile to make sure

  1. the efficiency is required (and a straightforward implementation is not fast enough for you)
  2. the method you're trying is faster than others for your application on real data

You could multiply by 10000, truncate as an integer, and divide again. Converting between double and int might be faster or slower for you.

You could truncate on output, e.g. a printf format string of "%.4f"

Matt Curtis
The platform is Linux 64bit.
Arman
+1  A: 

You could replace pow with a more efficient integer-based variant instead. There's one here on Stack Overflow: http://stackoverflow.com/questions/101439/the-most-efficient-way-to-implement-an-integer-based-power-function-powint-int

Also, if you can accept some inaccuracy, replace the divide with a multiply. Divisions are one of the slowest common math operations.

Other than that, I'll echo what others have said and simply truncate on output, unless you actually need to use the truncated double in calculations.

Blair Holloway
Very useful link, thanks!
Arman
+3  A: 
round(d*10000.0)/10000.0;

or if p must be variable;

double f = pow(10,p);
round(d*f)/f;

round will usually be compiled as a single instruction that is faster than converting to an integer and back. Profile to verify.

Note that a double may not have an accurate representation to 4 decimal places. You will not truly be able to truncate an arbitrary double, just find the nearest approximation.

drawnonward
Yes!the profiling shows it is faster than my version, thanks!
Arman
+1  A: 

If you need to perform exact calculations that involve decimal digits, then stop using double right now! It's not the right data type for your purpose. You will not get actually rounded decimal values. Almost all values will (after truncation, not matter what method you use) be in fact be something like 1,000999999999999841, not 1,0001.

That's because double is implemented using binary fractions, not decimal ones. There are decimal types you can use instead that will work correctly. They will be a lot slower, but then, if the result does not need to be correct, I know a method to make it infinitely fast...

Michael Borgwardt
What method is that? ;)
Alex
@Michael: Those calculations are done in double, then I do quick visualization using opengl, there I don't need an accuracy after 3,4-th digits. "I know a method to make it infinitely fast..."- could you please share that method?thanks.
Arman
@Arman: If you don't need accuracy after those digits, what's the point in truncating them? Why not just leave them in if they don't matter anyway? As for the last thing: if the calculations don't need to be correct, you can just hardcode an arbitrary result and not calculate anything. Another way to put it: "The most important optimization is where a program goes from not working to working".
Michael Borgwardt
Yes, maybe I need to redesign my algorithm.
Arman