0

I know that floating point cannot represent every number exactly so some error is bound to happen.

But recently I have encountered a problem and I am not getting the explanation right.

Please explain me step by step how the conversion affected the output.

How did truncating decimal places give me the wrong answer?

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

int main()
{
   int x;
   int y = 0;
   int n = 0;

   printf("Enter The Number You Want To Octal Equivalent Of : ");

   scanf("%d",&x);

   while(x>0)
   {
      y = y + (x%8)*pow(10,n);

      printf("%d\n" , y);

      x = x/8 ;
      n = n + 1;
   }

   printf("Octal Equivalent is : %d" , y);
   return 0;
}

When I enter find octal equivalent of 1701. It gives answer 3244.

What I want to know is how does the program working?
How is the program printing 3244 and not 3245.

But the answer is 3245.

I have checked that x%8 is correctly working .

When I change the y data type to float, it works . Why so?

Please explain me step by step how the conversion affected the output.
How did truncating decimal places give me the wrong answer?

Suraj Jain
  • 4,463
  • 28
  • 39
  • truncation and floating point error. – Daniel A. White Oct 25 '15 at 12:13
  • What i want to know is step by step how does truncating the decimal places give me 1 less than the intended answer. i don't know why people are down voting my question. – Suraj Jain Oct 25 '15 at 12:54
  • Your `pow(10,n)` is not providing the _exact_ expected answers. Add `printf("%.20e %d\n", pow(10,n), (int) pow(10,n));` to the loop to see the unexpected. – chux - Reinstate Monica Oct 10 '16 at 14:43
  • @chux Could you write the answer describing exactly the problem , after reading much i got to know that pow function is the cause. It would be better if you explain the problem , how does pow function do so, and the solution and why does your solution work. I would accept that answer if it would be satisfying – Suraj Jain Oct 10 '16 at 15:09
  • @chux Why does 99 comes ? And in exponential notation it is exact. So why does when we explicitly convert pow(10,n) to int then why does answer comess 99 instead of 100 ? – Suraj Jain Oct 10 '16 at 15:27
  • and if i use n = 2 , and use simply 2. Like pow(10,n) vs pow(10,2). In first case answer is 99 , and in second case answer is 100. Why so ? – Suraj Jain Oct 10 '16 at 15:29
  • @SurajJain Rather than _describe_ output like " And in exponential notation it is exact. ", post/comment the _exact_ output. I am confident that your did not get exact 100 output with `printf("%.20e %d\n", pow(10,n), (int) pow(10,n));`. – chux - Reinstate Monica Oct 10 '16 at 15:33
  • @chux When i use 2 instead of n , the output is 100. – Suraj Jain Oct 20 '16 at 12:03
  • @chux and in that case output is 1.0000000000000000000000e +002 99 – Suraj Jain Oct 20 '16 at 12:03
  • @chux So what i meant was in exponential notation it is somewhat accurate. – Suraj Jain Oct 20 '16 at 12:03
  • @SurajJain `"1.0000000000000000000000e +002 99'` is unexpected in 2 ways. 1) I _was_ expecting `"9.999999999999999.....e+01 99"`. It still is possible that the output is not showing sufficient precision. Request you try `printf("%.40e %d\n")` and `printf("%a %d\n")`. 2) the `+002` rather than `+02` implies a non-compilant C compiler. What compiler are you using? – chux - Reinstate Monica Oct 20 '16 at 15:40
  • @SurajJain IAC, better to use `round(pow(10,n));` than `pow(10,n);` to avoid the problem all together if you still desire to use the `pow()` approach. Better to use an integer only solution that does not involve FP math. – chux - Reinstate Monica Oct 20 '16 at 15:41
  • @chux using gcc 4.9.2 – Suraj Jain Oct 21 '16 at 08:36
  • @chux I will try to run it different this time . – Suraj Jain Oct 21 '16 at 08:40
  • @chux Also One thing i want to know is what do you think of this question and answer. "http://stackoverflow.com/questions/34826036/confused-pointer-dereferencing" . I Just want to ask is the answer to this question correct or not. Is it good or not. If you could check so it would be of great help. – Suraj Jain Oct 21 '16 at 08:40
  • @chux Code Is here http://paste.ofcode.org/BFZkkBHFN7HwM54KdwcEwU – Suraj Jain Oct 21 '16 at 08:46
  • @chux Output is : `1.00000000000000000000e+002 99` `1.0000000000000000000000000000000000000000e+002 99` `0xc.8p+3 99` – Suraj Jain Oct 21 '16 at 08:48
  • @chux Maybe what is happening is this http://stackoverflow.com/questions/24120888/why-printf-round-floating-point-numbers – Suraj Jain Oct 21 '16 at 08:54
  • Do not think the link at this [comment](http://stackoverflow.com/questions/33328560/float-to-integer-casting?noredirect=1#comment67611715_33328560) applies here. Neither the link [here](http://stackoverflow.com/questions/33328560/float-to-integer-casting?noredirect=1#comment67612170_33328560). IMO, code is complaint. Please report `#include printf("%d %.50Le\n", FLT_EVAL_METHOD, powl(10,n));` I think the issue is that intermediate calculations are being run in higher precision than `double` (allowed by C), yet that result is _just under_ 100. – chux - Reinstate Monica Oct 21 '16 at 14:11
  • @chux maybe it is rounding of , for example if i print 75.67 with %.1f , then answer comes 75.7 . so should not be that happening ? – Suraj Jain Oct 21 '16 at 18:27
  • @chux Please see this http://stackoverflow.com/questions/32231777/how-to-avoid-rounding-off-of-large-float-or-double-values The first answer. It clears the question. – Suraj Jain Oct 21 '16 at 18:29
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/126362/discussion-between-chux-and-suraj-jain). – chux - Reinstate Monica Oct 21 '16 at 20:34
  • @chux see chat. – Suraj Jain Oct 22 '16 at 17:28

2 Answers2

3

When you convert from a floating-point type to an integer type, the machine will truncate the decimal places, not round.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
  • can you elaborate?? where exactly is mistake done? when i add `printf("%d" , y);` it shows `5 45 244 3244`.. how is casting done? and you said machine will truncate decimal places not round ? but i converted only non decimal point integer to float. I mean if `x = 4`. then float `x = 4.00000`.So even if you truncate decimal places . Number should not change. Am i getting something wrong here? – Suraj Jain Oct 25 '15 at 12:38
  • Sir , i have to make a request. This question i asked because i need to know and it generated a down vote. Does this question deserved a down vote , it was a genuine doubt . Because of this i cannot ask questions as they are not respected. I want to know from you do you think this question is wrong and deserve downvotes? – Suraj Jain Oct 03 '16 at 02:58
0
Enter The Number You Want To Octal Equivalent Of : 1701
5
45
245
3245

try this see if it helps (dont need to link in a math library)

#include<stdio.h>
#include<stdlib.h>

int main()
{
int x;
int y = 0;
int n = 1;
printf("Enter The Number You Want To Octal Equivalent Of : ");
scanf("%d",&x);

while(x>0)
{
    y = y + ((x%8)*n);
    printf("%d\n" , y);

    x = x/8 ;
    n = n * 10;
    }


   printf("Octal Equivalent is : %d" , y);

   return 0;




    }

and I assume you know you can do this?

#include<stdio.h>
#include<stdlib.h>

int main()
{
int x;
int y = 0;
int n = 1;
printf("Enter The Number You Want To Octal Equivalent Of : ");
scanf("%d",&x);

while(x>0)
{
    y = y + ((x&7)*n);
    printf("%d\n" , y);

    x = x>>3 ;
    n = n * 10;
    }


   printf("Octal Equivalent is : %d" , y);

   return 0;




    }

or take an ascii approach

#include<stdio.h>
#include<stdlib.h>

int main()
{
    int x;
    int y = 0;
    int n = 0;
    char output[16];

    printf("Enter The Number You Want To Octal Equivalent Of : ");
    scanf("%d",&x);

    while(x)
    {
        output[n++]=(x&7)+0x30;
        x = x>>3 ;
    }
    output[n]=0x30;
    printf("Octal Equivalent is : ");
    while(n>=0)
    {
        printf("%c",output[n--]);
    }
    printf("\n");

    return 0;
}

or many other solutions...

#include<stdio.h>
#include<stdlib.h>

int main()
{
    int x;
    int y = 0;
    int n = 0;

    printf("Enter The Number You Want To Octal Equivalent Of : ");
    scanf("%d",&x);

    while(x)
    {
        y |= (x&7)<<n;
        n+=4;
        x>>=3;
    }
    printf("Octal Equivalent is : %X\n",y);
    return 0;
}

EDIT

1701 = 0x6A5 = 0b011010100101

so if you group the binary number in fours you can see the hex value (start from the right)

0110 1010 0101 = 0x6A5

if you break it into groups of three you see the octal

011 010 100 101 = 03245

and you can see how the last solution I showed works, tack a zero on each of these

011 010 100 101

0011 0010 0100 0101

and you get 0x3245, exactly what you were doing with base 10 but with base 16 instead and taking advantage of the optimization of using shifts and masks.

EDIT 2

understand how much is going on in this one line of code (assume x and y are int)

y = y + (x%8)*pow(10,n);

first off order of operations. the compiler is welcome to and should do the modulo first resulting in an int. Next order of operations, parenthesis would remove all doubt. the multiply is next but one operand is a double (pow) so the result of the modulo has to be promoted to double. and the double multiply happens. now you have the add one side is int the other double. so this y is promoted to double, the double add happens then the double to int happens to store in y. If you look at my first simpler example making n go 1, 10, 100, 1000, etc as an int then there is no double promotion it stays int all the time.

if you make y a float, then the add is a float + double so y has to be promoted to a double, the double add happens as before, but now the storage to the left side of the equals, as a float, you have a double to float conversion, which allows for rounding. so each time through the loop you allow the opportunity for a little fraction to land in y. problem here, at least with your examples, I dont see any fractions that the floating point format cannot handle. the modulo is supposed to be done as an int and there is no fraction. if you change x to a float, then sure you will have problems.

Suraj Jain
  • 4,463
  • 28
  • 39
old_timer
  • 69,149
  • 8
  • 89
  • 168
  • I did take y as float and it solved the problem and i tried your solutions too.What does `x = x>>3` means? – Suraj Jain Oct 25 '15 at 12:46
  • converting a number to octal from a binary perspective means take three bits at a time. take three off shift right three take three off, repeat until done. less computing power, but both solutions work. pow() drags double floats into the mix, which is way overkill for even a math base solution to the problem. that line shifts right 3 (divide by 2 to the power 3 = 8) shifts zeros in on the top – old_timer Oct 25 '15 at 16:26
  • 1
    `x = x>>3` is an obfuscated way of writing `x = x / 8` for positive numbers, and has not well-defined behaviour for negative numbers. – M.M Oct 09 '16 at 07:02
  • @SurajJain [read this](http://meta.stackexchange.com/questions/86997/what-can-i-do-when-getting-we-are-no-longer-accepting-questions-answers-from-th) – M.M Oct 10 '16 at 07:30
  • @dwelch SIr one more thing that i noticed was pow(10,n) where n = 2 gives me result 99. But pow(10,2) Gives 100. Why so ? – Suraj Jain Oct 20 '16 at 12:05
  • @old_timer SIr one more thing that i noticed was pow(10,n) where n = 2 gives me result 99. But pow(10,2) Gives 100. Why so ? – Suraj Jain Dec 29 '16 at 14:19