bjar-bjar
bjar-bjar

Reputation: 707

Reducing the digits of a Double in C++

I need a function that reduces the precision (number of digits) of my doubles.

I need it for calculation, not for output on the screen.

What I have so far, is:

double setDigits(double _number, int _digits)
{
    double tenth = pow((double)10,_digits);
    _number *= tenth;
    _number = floor(_number);
    _number /= tenth;

    return _number;
}

calling setDigits(sqrt(2),3) gives 1.4139999999999999, and not 1.414 as I want.

What can I do?

Upvotes: 3

Views: 2744

Answers (6)

dreamcrash
dreamcrash

Reputation: 51443

double setDigits(double _number, int _digits)
{
       double tenth = pow((double)10,_digits);
       int result = (_number * tenth) + 0.5; 
       double aux = result / tenth;

       return aux;
}

Try the following with tenth = 1000;

result = 1413,9999999999999 * 1000 +0,5
result = 1414,4......
result = 1414

Upvotes: 0

roohi
roohi

Reputation: 1

i don't know you may not check this answer but others do i am new in c++ but i found a way to do this

double Point::norm()

{

return (double)floor((sqrt(pow(px,2)+pow(py,2)+pow(pz,2))*1000))*0.001;

}

i use this but you can write your own math class to do this for you

Upvotes: 0

Gorpik
Gorpik

Reputation: 11028

You can create an intermediate class that manages data internally as int, but inputs and outputs as double:

class TruncatedDouble
{
private:
  int value_;

public:
  TruncatedDouble(double d) : value_((int)(double * 1000)) {}
  void SetValue(double d) {value_ = (int)(double * 1000);}
  double GetValue() {return (double)value_ / 1000;}
};

You have to overload all the usual operators too, but that's easy. Example:

TruncatedDouble& operator+=(const TruncatedDouble& rh) {value_ += rh.value_;}

And so on. This class will actually be quite fast, since you are operating with int instead of double, and you will never lose precision.

Upvotes: -1

abhshkdz
abhshkdz

Reputation: 6365

The following lines are invalid.

double tenth = pow((double)10,_decimals); //_decimals is not declared
_number = floor(_digits); //should be floor(_number)

The corrected function is

double setDigits(double _number, int _digits)
{
    double tenth = pow((double)10,_digits);
    _number *= tenth;
    _number = floor(_number);
    _number /= tenth;

    return _number;
}

Here is a demo.

Upvotes: 3

LSerni
LSerni

Reputation: 57408

What can I do?

Unfortunately, nothing for the root problem: in your platform, 1.414 has no exact double representation. You can't run a calculation with "1.414" because you can't place "1.414" anywhere in your double.

See for example http://www3.ntu.edu.sg/home/ehchua/programming/java/DataRepresentation.html .

What you can do is to keep your number with the maximum precision, and display it with reduced precision. You need to calculate machine precision and keep track of error during computation.

So you'll use 1.413999999999997 and at the end get an answer of, say, 41.99999137; which you'll display with

printf("The answer is %.3f\n", theAnswer);

Or you can change platform (compiler, or math library, or floating point representation, e.g. use long double where supported), but remember that you can then get 1.414 right at the price of getting, say, 1.873 wrong (have it as 1.87299999999 or 1.87300000001), and the calculation will have more or less the same errors.

You can work in integer arithmetic, multiplying the initial numbers by 1,000,000 (and getting 1414000) or another suitable scale, and then dividing at the end. Integers have a maximum bound, though.

There are also Arbitrary Precision Libraries that use a different internal representation and allow you to specify precision the way you want, for example GMP ( http://gmplib.org/ ). Of course, working with that is more difficult than specifying

op1 = 6.0;
op2 = 7.0;
theAnswer = op1 * op2;

and processing is slower as well, but results are good - or as good as you tell them to be.

Upvotes: 5

Denis Ermolin
Denis Ermolin

Reputation: 5546

Try this:

double setDigits(double _number, int _digits)
{
    double tenth = pow((double)10,_digits);
    return floor(_number * tenth + 0.5)/tenth;
}

std::cout<<setDigits(sqrt(2),3);

Output: 1.414

Upvotes: -1

Related Questions