Skip to content
Lesson 3 of 13

Step 1 of 5 · Reading · ~3 min

Learn

Getting Started

Numbers and printf

By the end of this lesson you can predict what C arithmetic produces before you run it, and print integers and decimals in exactly the format a grader expects. Two rules do most of the work: the operands decide the arithmetic, and each printf specifier is a promise about the type of the next argument.

Integer division truncates

printf("%d\n", 7 / 2);     /* 3  - int / int stays int, fraction dropped */
printf("%d\n", 7 % 2);     /* 1  - remainder */
printf("%d\n", 99 / 100);  /* 0  - the "percentage is always zero" classic */
printf("%f\n", 7.0 / 2);   /* 3.500000 - one double makes it a double division */

The type of a division is decided by its operands, not by where the result goes. double d = 7 / 2; stores 3.0: the division finished in integer land before the assignment happened. To keep the fraction, cast one operand first. A cast is a type name in parentheses in front of a value, and it converts that value:

int points = 17;
int games = 4;
double wrong = points / games;           /* 4.00 - truncated, then widened */
double avg = (double)points / games;     /* 4.25 - double / int is a double division */

The cast must sit on an operand. (double)(points / games) is still 4.00, because the inner parentheses make the integer division run first.

Integer overflow

An int holds at most 2,147,483,647. Multiply two large ints and the result does not fit; for signed types this is undefined behaviour, and on this grader you typically see a wrapped, often negative, number. Widening the result variable is not enough, for the same reason as with division:

int rows = 60000;
int per_row = 50000;
long long bad  = rows * per_row;               /* int * int overflows first */
long long good = (long long)rows * per_row;    /* 3000000000 */

long long is 64-bit (up to about 9.2 * 10^18). Cast one operand before the multiply, and print the result with %lld.

printf: the specifier contract

SpecifierArgument typeExamplePrints
%dintprintf("%d", 42)42
%lldlong longprintf("%lld", 3000000000LL)3000000000
%fdoubleprintf("%f", 4.25)4.250000
%.2fdoubleprintf("%.2f", 4.256)4.26
%.1fdoubleprintf("%.1f", 0.04)0.0

%f alone always prints six decimals, so a grader expecting 4.25 rejects 4.250000. %.2f prints exactly two and rounds (4.256 becomes 4.26, not 4.25), so you never round by hand.

Mismatch a specifier and its argument and you get undefined behaviour, not an error: printf("%f\n", 15) prints 0.000000 here, and printf("%d\n", 4.25) prints an unrelated integer. gcc -Wall warns about both at compile time, so read the warnings.

Common mistakes

  • Dividing two ints and hoping for a fraction. (double)(a / b) or double r = a / b; gives 3.00 where 3.50 was wanted, and 0.00 whenever the top number is smaller than the bottom one.
  • Multiplying two ints into a long long. The product overflows before the assignment, so 46341 * 46341 prints a negative number instead of 2147488281.
  • Wrong specifier. %d for a long long or %f for an int prints garbage; %f for a decimal prints six places instead of two.
  • Extra text. Area: 15 fails where 15 passes; the comparison is on every character.

Your exercise

Given a rectangle's width and height, print its area and its width-to-height ratio. The starter reads both numbers as int; you write the arithmetic and the two printf calls. The mistake the hidden tests are waiting for is an integer division or an integer multiply that happens before any conversion.

Up nextArraysArrays and Strings

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…