28

I am trying to print some floating point numbers using printf. For example:

int main()
{
    printf("%.1f",76.75); 
    return 0;
}

Output: 76.8

And I have some questions about the result.

First of all, why didn't it print 76.7?

Second, how did it round the number?

7
  • 7
    why it should print 76.7? Commented Jun 9, 2014 at 13:04
  • 4
    @ecatmur: The answers to that question blame floating-point rounding errors, but this is a different situation because the number 76.75 is represented exactly. Commented Jun 9, 2014 at 13:09
  • FWIW, your caption is: "Why (does) printf round floating point numbers?". Well, because you tell it to, with the %.1f formatting string. Commented Jun 9, 2014 at 16:43
  • 2
    @RudyVelthuis That question is “Why does 37.975 not convert to 37.98?”. This question is “Why does 76.75 convert to 76.8?”. They are symmetrically opposed questions. Besides, the answers there blame rounding in the decimal-to-floating-point conversion that happened during the compilation of 37.975. The correct answer here should explain that this is the normal rounding behavior of floating-point-to-decimal conversion for a value that is exactly midway between two decimal representations. Commented Jun 9, 2014 at 17:02
  • 2
    @Pascal: I see it now: the close vote. No, it is not a duplicate, IMO. Commented Jun 9, 2014 at 17:08

3 Answers 3

24

C99 §7.19.6.1 The fprintf function

f,F

A double argument representing a floating-point number is converted to decimal notation in the style [−]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; if the precision is zero and the # flag is not specified, no decimal-point character appears. If a decimal-point character appears, at least one digit appears before it. The value is rounded to the appropriate number of digits.

Sign up to request clarification or add additional context in comments.

1 Comment

Ah, but what does "rounded" mean? One might naïvely think that it means "to the nearest", with some wiggle room around 0.5, but note that the C standard defines four different rounding modes (ref 7.6) and the core standard declines to specify a default, so it isn't clear which one of them "rounded" refers to. If you believe that it follows the rounding mode (which the standard does not require), then deep in the weeds you find F.7.3 (C99, F.8.3 in C11 and C17), which specifies that the default rounding mode is "to nearest".
16

In addition to existing answers, note that many C compilers try to follow IEEE 754 for floating-point matters. IEEE 754 recommends rounding according to the current rounding mode for conversions from binary floating-point to decimal. The default rounding mode is “round to nearest and ties to even”. Some compilation platforms do not take the rounding mode into account and always round according to the default nearest-even mode in conversions from floating-point to decimal.

Since 76.75 represents the number 7675/100 exactly, it is precisely halfway between 76.7 and 76.8. The latter number is considered the “even” one when applying “round to nearest-even”. This is probably why your compilation platform chose to generate this decimal representation as the conversion to decimal of the floating-point number 76.75.

10 Comments

I've never seen printf round according to the current rounding mode. (I haven't looked in years, though. All I saw was round-to-even and round-to-Java.) Which implementations do that?
@tmyklebu Mac OS X. Linux always rounds to nearest-even, even if the rounding mode was changed. pastebin.com/p3myWBQU (obtained on Mac OS X). Microsoft's compiler has bigger problems than the rounding direction, so I don't think anyone cares about that.
@tmyklebu: always willing to learn something new, so what on earth is round-to-Java? Do you have a link?
@RudyVelthuis: As I recall, it always rounds "1/2" up. Namely, System.out.printf("%.2f", 0.745); outputs 0.75, even though the double 0.745` is strictly less than the rational number 745/1000.
@tmyklebu This is a bad example as 0.745 is not exact. Or perhaps it is a good example of the “Java rounding”, because Java prints it as exact with %.53f. So “Java rounding” would actually appear to be “print as many decimals as required to make the value unambiguous in the origin floating-point type, then apply the rounding rule from primary school”. 0.745 is less than 745/1000 and gets rounded to 0.75. Brilliant! Anyway, if you do not wish to get into the discussion of why Java is <profanity buzzer>, a better example is 0.25.
|
8

First of all, why he didn't print 76.7?

Because the language specification says that the low-order digit will be rounded.

how he rounded the number? (some code would help)

This differs implementation-by-implementation. According to the documentation,

The low-order digit shall be rounded in an implementation-defined manner (emphasis added).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.