Compound Assignment Operator returning a wrong value (Decimal to Binary Conversion)

29 Views Asked by At

I'm trying to write a C Program to convert a Decimal to Binary. The following code can convert an Integer in Decimal to Binary.

#include <stdio.h>
#include <math.h>

int main()
{
    long int n;
    printf("Enter a Positive Integer (decimal): ");
    scanf("%d", &n);
    long int temp = n;
    int r;  long long int bin = 0;
    int p = 0;

    while(temp > 0)
    {
        r = temp % 2;   printf("%d\t", r); // printing r value for debugging
        bin += (r * pow(10, p));
        temp /= 2;
        p++;
    }
    printf("\n%lld", bin);
    
    return 0;
}

I have tested the code for multiple random values and got the expected output for most of them except two particular values '99999' and '419862'. For '99999', the expected output is '11000011010011111', But instead I get '11000011010011112'. And for '419862', the expected output is '1100110100000010110', But instead I get '1100110100000010112'. All digits but the last one's match correctly. Getting a '2' instead of '1' and '0'. To Debug the code I added a printf("%d\t", r); immediately after the r = temp % 2; statement. The r values so printed give the correct expected output. Here is the output:

For '99999' the output is

Enter a Positive Integer (decimal): 99999
1   1   1   1   1   0   0   1   0   1   1   0   0   0   0   1   1   
11000011010011112

For '419862' the output is

Enter a Positive Integer (decimal): 419862
0   1   1   0   1   0   0   0   0   0   0   1   0   1   1   0   0   1   1   
1100110100000010112

Caution: The r values printed individually are in reverse.

Why is the first remainder value printed using printf("%d\t", r); '1' and '0' respectively (for '99999' and '419862'), But the unit digits of bin value obtained by Compound Assignment not the same?

1

There are 1 best solutions below

1
MikeCAT On

bin += (r * pow(10, p)); means bin = bin + (r * pow(10, p));. (N1570 6.5.16.2 Compound assignment)

According to usual arithmetic conversions (N1570 6.3.1.8), multiplication * and addition + will yield double result when one of their operands is double (and the other one is real type and not long double).

The pow function (N1570 7.12.7.4) returns double, so r * pow(10, p) has type double, and therefore bin + (r * pow(10, p)) also has type double.

Typically 64-bit IEEE754 format is used for double. It is said that the presicion of this format is about 15 decimal digits.

In the last iteration with input 99999, values 1000011010011111 and 10000000000000000 are added. They has 16 and 17 digits, respectively. This exceeds the 15-digit limit and the chance to get precision errors becomes high.

In conclusion, you are getting rounding error because you used floating-point values where integers with many digits should be used.

For example, the use of pow in this case can be eliminated in this way (use a multiplier variable mult and incrementaly multiply 10 to that instead calculating the power in each iteration):

    long long int mult = 1;
    while(temp > 0)
    {
        r = temp % 2;   printf("%d\t", r); // printing r value for debugging
        bin += (r * mult);
        temp /= 2;
        mult *= 10;
    }