0

I'm trying to finish some basic coding exercise and I have already figured out how to fix it but I would just really like to understand what's going on.

#include <stdio.h>
#include <math.h>
int main(void) {
    int first, second, third, fourth, fifth, sumOne, sumTwo, product;

    printf("Enter integer 1: ");
    scanf("%d", &first);
    printf("Enter integer 2: ");
    scanf("%d", &second);
    printf("Enter integer 3: ");
    scanf("%d", &third);
    printf("Enter integer 4: ");
    scanf("%d", &fourth);
    printf("Enter integer 5: ");
    scanf("%d", &fifth);

    sumOne = first + second;
    sumTwo = third + fourth;

    printf("Result = %d", pow ((sumOne * sumTwo), fifth));

    return 0;

    
}

I have been reading and I found out that pow provides a double result. I found that by changing the placeholder on the last printf() statement to %.0f, I get the desired result. Reason why I used %d is because I didn't want to get decimals in the output. I could also modify the data type and to double instead of int and just limit the decimals again on the final result.

I think my question is why have I been getting incorrect result with the use of %d as placeholder? Thank you.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
ddp17
  • 41
  • 4
  • 1
    `printf` requires the type specifier and the corresponding variable argument to match. If you want to use `%d`, cast the result of `pow` to an `int`. – jxh Oct 04 '22 at 16:15
  • 4
    For integer powers, don't use the floating point `pow` function, create your own. But beware of possible overflow. – Some programmer dude Oct 04 '22 at 16:15
  • 2
    If you only want to print the integer portion of a floating point value, use `%.0f` or `%.0lf` – William Pursell Oct 04 '22 at 16:21

3 Answers3

2

The function pow is declared like

double pow(double x, double y);

That is its return type is double. So you need to write using the conversion specifier f instead of d

printf("Result = %f", pow ((sumOne * sumTwo), fifth));

I think my question is why have I been getting incorrect result with the use of %d as placeholder?

double numbers usually occupy 8 bytes (objects of the type int usually occupy 4 bytes) and have internal representation that differ from the internal representation of integers.

You could cast the result of the call of pow to the type int and in this case use the conversion specifier d.

printf("Result = %d", ( int )pow ((sumOne * sumTwo), fifth));

Or you could round the result of the call of pow before outputting it as an integer.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I'm ok with the first part of your answer. But not the second. If it is really important that the exponentiation is integer (and printed with ``%d``) then op should not use ``pow`` at all. ``pow(a,b)`` is basically ``exp(b*log(a))``. – chrslg Oct 04 '22 at 16:22
  • So, not only is uses floating point operation that may be costly (ok, nowadays, nobody cares anymore). But more importantly, it is a float. So, for example, what if the result is ``255.9999999999999999999`` as it could be? – chrslg Oct 04 '22 at 16:24
  • Correct answer to the 2nd part has been given in comments to the question: "don't use pow for integer". And if you really must, and want to print only the integer part, use "%.0f" – chrslg Oct 04 '22 at 16:25
  • @chrslg The question is about conversion specifiers and why you may not use the conversion specifier d with floating numbers in calls of printf. – Vlad from Moscow Oct 04 '22 at 16:27
  • Yeah, I get that. That is why I upvoted. But, again, casting 255.9999999999999 would not lead to the wanted output. – chrslg Oct 04 '22 at 16:30
  • @chrslg and use `round()`. – Weather Vane Oct 04 '22 at 17:54
  • Sure. Let go. I obviously don't explain myself correctly if people think that I need to know about round. I was talking about the ``(int)`` solution. I don't really need to know how to solve the problem myself – chrslg Oct 04 '22 at 18:00
0

A printf conversion specification generally tells printf two things: what type of argument to expect and what to do with it.

For example:

  • %d says expect an int argument and print it as a decimal numeral.
  • %c says expect an int argument, convert it to an unsigned char, and print the character with that code.
  • %f says expect a double argument and print it in decimal notation with six digits after the decimal point.
  • %e says expect a double argument and print it in scientific notation.

The conversion specification needs to tell printf the type of the argument because nothing in the regular C function-call mechanism tells the called function what the argument types are. A function has to be either defined with certain types or it has to be told what the types are through some other mechanism. For printf, that mechanism is the format string.

When you pass the result of pow, you pass a double argument, but %d tells printf to expect an int argument. Since these are different types, represented with different encoding methods, and may be passed in different places in the processor or memory, printf is unable to find and decode the argument you passed. The C standard does not define the behavior when you pass an argument of the wrong type for a printf conversion specification.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

I think my question is why have I been getting incorrect result with the use of %d as placeholder? Thank you.

%d expects its corresponding argument to have type int; pow returns a double. These types have different sizes and different representations - the binary representation of 123.0 (double) is completely different from the binary representation of 123 (int):

123   = 00 00 00 7b 
123.0 = 40 5e c0 00 00 00 00 00 

Because of how printf is defined, it doesn't know the actual types of its arguments - it doesn't know that the argument corresponding to the result of pow is a double instead of an int. Instead, it expects the first argument to be an int because you used %d, so it's not interpreting that value correctly.

Crank up your warnings on your compiler.

John Bode
  • 119,563
  • 19
  • 122
  • 198