Truncating decimal places in a float (possibly OT)

T

Todd

I have a function that takes a double and truncates it to a specified
number of decimal places. I've found that I have to add a small
number to the input value otherwise I get errors due to the way
floating points work.

double TruncateToDigits(double dValue, int iDigitsToRightOfDecimal)
{
double dEpsilon = 1e-8;
// high limit, about 100,000,000 for this epsilon (1e-8)
// low limit, about 7 decimal places for this epsilon (1e-8)
// modifying it will increase one limit while reducing the other
ASSERT(fabs(dValue) < 100000000.0);
ASSERT(iDigitsToRightOfDecimal <= 7);

int iSignFactor = (dValue >= 0.0 ? 1 : -1);
dValue *= iSignFactor; // make positive
dValue += dEpsilon; // make it error towards the positive
double dMulti = pow(10.0, iDigitsToRightOfDecimal);
dValue *= dMulti; // move valid digits left of decimal
dValue = floor(dValue); // truncate to whole value
dValue /= dMulti; // move digits back
dValue *= iSignFactor; // put sign back
return dValue;
}

This appears to work, however it only reliably works within a certain
range, as listed in the comments.

Is there a better way to do this? One that would work for any
floating point range?
 
T

Todd

What does that mean? How would it "truncate" 0.111 to 1 decimal point
when neither 0.111 nor 0.1 can be represented _exactly_ in the binary
system of FP numbers (employed by most computers nowadays)?

To be more specific, the input is a fixed decimal place number
(converted to a double) and the output needs to be the floating point
closest to the truncated decimal number. If that makes sense.
 
S

sonison.james

To be more specific, the input is a fixed decimal place number
(converted to a double) and the output needs to be the floating point
closest to the truncated decimal number.  If that makes sense.

How about doing it using strings.

#include <sstream>
#include <string>
#include <iostream>
using namespace std;

double foo( double d, size_t n )
{
stringstream ss;
ss.setf( ios::fixed, ios::floatfield );
ss << d;
n += ss.str().find( '.' ) + 1;
string str = ss.str().substr( 0, n );
stringstream ss2;
ss2 << str;
double d2;
ss2 >> d2;

return d2;
}

int main()
{
double d = 1.1234567;
cout << "1 decimal place:" << foo( d, 1 ) << endl;
cout << "2 decimal place:" << foo( d, 2 ) << endl;
cout << "3 decimal place:" << foo( d, 3 ) << endl;
cout << "4 decimal place:" << foo( d, 4 ) << endl;
cout << "5 decimal place:" << foo( d, 5 ) << endl;

return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top