Search code examples
cbignum

Convert continues binary fraction to decimal fraction in C


I implemented a digit-by-digit calculation of the square root of two. Each round it will outpute one bit of the fractional part e.g.

1 0 1 1 0 1 0 1 etc.

I want to convert this output to decimal numbers:

4 1 4 2 1 3 6 etc.

The issue I´m facing is, that this would generally work like this:

1 * 2^-1 + 0 * 2^-2 + 1 * 2^-3 etc.

I would like to avoid fractions altogether, as I would like to work with integers to convert from binary to decimal. Also I would like to print each decimal digit as soon as it has been computed.

Converting to hex is trivial, as I only have to wait for 4 bits. Is there a smart aproach to convert to base10 which allows to observe only a part of the whole output and idealy remove digits from the equation, once we are certain, that it wont change anymore, i.e.

1   0
2   0,25
3   0,375
4   0,375
5   0,40625
6   0,40625
7   0,4140625
8   0,4140625

After processing the 8th bit, I´m pretty sure that 4 is the first decimal fraction digit. Therefore I would like to remove 0.4 complelty from the equation to reduce the bits I need to take care of.


Solution

  • The issue I´m facing is, that this would generally work like this:

    1 * 2^-1 + 0 * 2^-2 + 1 * 2^-3 etc.

    Well 1/2 = 5/10 and 1/4 = 25/100 and so on which means you will need powers of 5 and shift the values by powers of 10

    so given 0 1 1 0 1

    [1] 0 * 5 = 0

    [2] 0 * 10 + 1 * 25 = 25

    [3] 25 * 10 + 1 * 125 = 375

    [4] 375 * 10 + 0 * 625 = 3750

    [5] 3750 * 10 + 1 * 3125 = 40625

    Edit:

    Is there a smart aproach to convert to base10 which allows to observe only a part of the whole output and idealy remove digits from the equation, once we are certain, that it wont change anymore

    It might actually be possible to pop the most significant digits(MSD) in this case. This will be a bit long but please bear with me

    Consider the values X and Y:

    1. If X has the same number of digits as Y, then the MSD will change.
        10000 + 10000 = 20000
    
    1. If Y has 1 or more digits less than X, then the MSD can change.
        19000 + 1000  = 20000
        19900 +  100  = 20000
    

    So the first point is self explanatory but the second point is what will allow us to pop the MSD. The first thing we need to know is that the values we are adding is continuously being divided in half every iteration. Which means that if we only consider the MSD, the largest value in base10 is 9 which will produce the sequence

        9 > 4 > 2 > 1 > 0
    

    If we sum up these values it will be equal to 16, but if we try to consider the values of the next digits (e.g. 9.9 or 9.999), the value actually approaches 20 but it doesn't exceed 20. What this means is that if X has n digits and Y has n-1 digits, the MSD of X can still change. But if X has n digits and Y has n-2 digits, as long as the n-1 digit of X is less than 8, then the MSD will not change (otherwise it would be 8 + 2 = 10 or 9 + 2 = 11 which means that the MSD will change). Here are some examples

    Assuming X is the running sum of sqrt(2) and Y is 5^n:

     1. If X = 10000 and Y = 9000 then the MSD of X can change.
     2. If X = 10000 and Y =  900 then the MSD of X will not change.
     3. If X = 19000 and Y =  900 then the MSD of X can change.
     4. If X = 18000 and Y =  999 then the MSD of X can change.
     5. If X = 17999 and Y =  999 then the MSD of X will not change.
     6. If X = 19990 and Y =    9 then the MSD of X can change.
    

    In the example above, on point #2 and #5, the 1 can already be popped. However for point #6, it is possible to have 19990 + 9 + 4 = 20003, but this also means that both 2 and 0 can be popped after that happened.

    Here's a simulation for sqrt(2)

    i          Out                      X                  Y     flag
    -------------------------------------------------------------------
    1                                   0                  5       0
    2                                  25                 25       1
    3                                 375                125       1
    4                               3,750                625       0
    5                              40,625              3,125       1
    6                             406,250             15,625       0
    7            4                140,625             78,125       1
    8            4              1,406,250            390,625       0
    9            4             14,062,500          1,953,125       0
    10          41             40,625,000          9,765,625       0
    11          41            406,250,000         48,828,125       0
    12          41          4,062,500,000        244,140,625       0
    13          41         41,845,703,125      1,220,703,125       1
    14         414         18,457,031,250      6,103,515,625       0
    15         414        184,570,312,500     30,517,578,125       0
    16         414      1,998,291,015,625    152,587,890,625       1
    17        4142      0,745,849,609,375    762,939,453,125       1