Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decimal To Octal Converter, last digit issue

Tags:

c

decimal

octal

I tried making a C program to convert a user entered decimal number to octal. I wrote the C code with my own logic without any research of how other users try to do it. It works fine for the number 601 and some other numbers but for most numbers it returns the octal equivalent with the last digit being 1 less than it should be. For 75 it returns 112 instead of 113. I realize using printf with %o gets the job done but it's kind of defeating the purpose of learning to program. Here's my code:

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

/* converting decimal to octal */

int main() 
{
    int n,x,y,p,s;
    printf("Enter a decimal number ");
    scanf("%d",&x);
    s=0;p=0;

    while (x!=0)
    {
         y=x%8;
         s=s+y*pow(10,p);
         x=(x-y)/8;
         p=p+1;
    }  

  printf("the octal equivalent is: %d\n",s);
  getch();
  return 0;
}
like image 645
Srishan Supertramp Avatar asked Nov 02 '12 04:11

Srishan Supertramp


People also ask

What are the rules to convert a decimal number into an octal number?

In decimal to binary, we divide the number by 2, in decimal to hexadecimal we divide the number by 16. In case of decimal to octal, we divide the number by 8 and write the remainders in the reverse order to get the equivalent octal number.

Why is there no 8 and 9 in octal?

You will never see 8 or 9 in any of the numbers in the octal system. The base of the octal number system or radix is 8. This is because the total number of digits in the number system is 8. The positional value of the digits in the octal system can be written in terms of 8 raises to the power the positional number.

How do you convert decimal numbers to octal numbers explain with an example?

Example − Convert decimal number 136 into octal number. Divide the decimal number by the largest power of eight. = 136 / 64 = 2.125 So 2 will be first digit or most significant bit (MSB) of octal number. Now, remainder will be, = 136 - 642 = 8 Now, divide this remainder by the next power of 8.


2 Answers

That's an interesting way to do it. I'll give an up-vote on the question just for originality.

Fix the problem by adding a fudge factor:

s = s + y*pow(10,p) + 0.1;

The problem is floating point accuracy. One of those pow calculations is returning something like 99.99999999999992 instead of 100. Converted back to int loses the 0.999... fraction and gets 99 instead of 100. Or 999 instead of 1000. It's not in the one's place because a zero exponent is a special case that gets 1.0 exactly.

By the way, since you can only get 9 digits in a 32-bit int, so susmit's suggestion of multiplying out the power of 10 in int form is quite reasonable. Except in special cases, pow will compute pow(x,y) as exp(y*log(x)). exp() and log() tend to be expensive computations.

Even more by the way, I'm unable to reproduce that problem, even by forcing exp and log computations. I get values of (10 + 1.8e-15), (100 + 4.3e-14) and (1000 + 6.8e-13), all rounding correctly because the error as all positive. This is on a x86 and I believe I compiled this calculator with VC++2008. What compiler are you using?

like image 188
Mike Housky Avatar answered Sep 29 '22 05:09

Mike Housky


Alternative to first answer, instead of

s=s+y*pow(10,p);

have a shiftfactor, initialized to one, and do

s += y*shiftfactor;
shiftfactor *= 10;

Additionally, instead of x=(x-y)/8; it is enough to do just x/=8; due to integer rounding.

like image 29
hyde Avatar answered Sep 29 '22 07:09

hyde