Question

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;
}
Était-ce utile?

La solution

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?

Autres conseils

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.

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

/* converting decimal to octal */

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

   p = 0;

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

printf("the octal equivalent is: %lf\n",s);

return 0; }

I think this will solve your problem. Actually the Pow() returns double value. In your code you have used the int so the fractional part will be truncated and the put in the variable 's'.

#include <stdio.h>
int main()
{
    int d_num = 0;
    int o_num = 0;
    int factor = 1;

    printf("Enter a decimal number: ");
    scanf("%d", &d_num);

    while (d_num > 0) {
            o_num += d_num % 8 * factor;
            d_num /= 8;
            factor *= 10;
    }

    printf("Octal equivalent: %d\n", o_num);
    return 0;
}

To me this code works fine with only integer operations.

Why do u need to use x=(x-y)/8. Why can't u use x=x/8. Its the same effect as type of the variables used in lhs and rhs are all integers. By the way code is working for me. I think issue is with integer rounding. Just replacing the x=(x-y)/8 with x=x/8

OP solved this problem some time ago, but thought I'd present a simply solution.

/* converting decimal to octal */
unsigned decimal_to_octal(unsigned x) {
  if (x < 8) {
    return x;
  }
  return decimal_to_octal(x/8)*10 + x%8;
}

Test code

unsigned test10to8(void) {
  for (;;) {
    unsigned x;
    scanf("%d", &x);
    printf("x:%u y:%u\n", x, decimal_to_octal(x));
  }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top