Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display precisely the decimal digits of a double in C++?

Problem
Given two integers a, b, a < b. Display its decimal expansion. You will print the decimal expansion of integer quotient given, stopping just as the expansion terminates or just as the repeating pattern is to repeat itself for the first time. If there is a repeating pattern, you will say how many of digits are in the repeating pattern.

Sample Input
3 7
345 800
112 990
53 122

Sample Output
.428751
The last 6 digits repeat forever.
.43125
This expansion terminates.
.113
The last 2 digits repeat forever.
.4344262295081967213114754098360655737704918032786885245901639
The last 60 digits repeat forever.

Note: This problem is original from the ProgFest programming contest.

The algorithm for this problem is not difficult if we apply these three theorems: enter image description here

However, the problem that I'm facing is the rounding-off when calculating alpha using the recursive formula given in Theorem 1. The display function is defined as follows:

void displayFraction( int n, int d, int length ) {
    std::cout << ".";
    double alpha = static_cast<double>( n ) / d;
    for( int i = 1; i <= length; ++i ) {
        int c = std::floor( 10.0 * alpha );
        alpha = 10.0 * alpha - c;
        std::cout << c;
    }
}

And my output was:

.4344 2622 9508 1967 3732 7807 5683 6291 4025 7835 3881 8359 3750 0000 0000 0

where the problem output was:

.4344 2622 9508 1967 2131 1475 4098 3606 5573 7704 9180 3278 6885 2459 0163 9

As you can see, it was correct up to the 16th digit. So my question is, how I can prevent the truncating digits when performing the calculation in this particular situation? Any idea?

like image 515
Chan Avatar asked Jul 11 '11 08:07

Chan


3 Answers

The problem is that double doesn't have infinite amounts of precision, but instead can only manage about 16 decimal digits worth. Which is where you run into trouble (funny, that!) as the fundamental lack of information in the input double shows up.

You need to find a way of tackling the problem that will keep getting closer to the answer as you get more digits out of it. That means you'll need to think much more about Theorem 3, and also work on writing your code in terms of rationals instead of floating point.

like image 60
Donal Fellows Avatar answered Nov 10 '22 18:11

Donal Fellows


Use a bignum library like gmp. There's only so much information you can pack into a double.

like image 27
György Andrasek Avatar answered Nov 10 '22 17:11

György Andrasek


I think you want an arbitrary precision library

Something like the gnu MP bignum, although other flavours are available

like image 2
Tom Avatar answered Nov 10 '22 16:11

Tom