sprintf formats not as expected

257 views Asked by At

I've got a problem with rounding using sprintf. I get passed '%0.0f' as the format. sprintf rounds not as expected: 0.5 should be rounded to 1, instead it rounds to 0, which is against the general rounding rule, whereas 1.5, 2.5 etc. is being rounded correctly:

sprintf('%0.0f', 0.5)
=> "0"


sprintf('%0.0f', 1.5)
=> "2"

Why is this so and how can I achieve my expected behaviour?

3

There are 3 answers

6
Mark Thomas On BEST ANSWER

sprintf performs banker's rounding, which rounds 0.5 to the nearest even number. This method is often used by statisticians, as it doesn't artificially inflate averages like half-up rounding.

The Float#round method (in Ruby 2.4+) accepts a parameter which can be one of:

  • half: :up (the default)
  • half: :down
  • half: :even (banker's rounding)

Apparently you are expecting round's default, so you can just do a .round to your number before printing.

0
imbuedHope On

This is expected behavior for printf. The default rounding mode is to round to the nearest valid value, and in case of a tie to pick the even number. Since 0.5 is treated as being in exactly the middle of 0 and 1, it tends to 0 because it is the even number.

0
7stud On

how can I achieve my expected behaviour?

Round the float before you give it to sprintf:

2.4.0 :001 > sprintf('%0.0f', 0.5.round)
 => "1" 

2.4.0 :002 > sprintf('%0.0f', 1.5.round)
 => "2"