Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do programming languages round down until .6?

If you put a decimal in a format where has to be rounded to the nearest 10th, and it is: 1.55, it'll round to 1.5. 1.56 will then round to 1.6. In school I recall learning that you round up when you reach five, and down if it's 4 or below. Why is it different in Python, et al.

Here's a code example for Python 2.6x (whatever the latest version is)

'{0:01.2f}'.format(5.555)  # This will return '5.55' 

After trying some of the examples provided, I realized something even more confusing:

'{0:01.1f}'.format(5.55)  # This will return '5.5' # But then '{0:01.1f}'.format(1.55)  # This will return '1.6' 

Why the difference when using 1.55 vs 5.55. Both are typed as literals (so floats)

like image 939
orokusaki Avatar asked Jan 06 '10 16:01

orokusaki


People also ask

Do programming languages round up or down?

Because it is just smaller than 1.55, it rounds down when it is rounded to one digit after the decimal point, giving the result "1.5" that you're observing. Note that both values round to even numbers; neither rounds to "1". Show activity on this post.

Why do we round 5 up and not down?

If there is a non-zero digit, then we round up, because the number is greater than 0.15. Either way we round up, which means that we don't actually need to bother looking at any places to the right of the hundredths place to determine our action. What if the rule was that we round down?

Does 6 round up or down?

Here's the general rule for rounding: If the number you are rounding is followed by 5, 6, 7, 8, or 9, round the number up. Example: 38 rounded to the nearest ten is 40. If the number you are rounding is followed by 0, 1, 2, 3, or 4, round the number down.

Why do numbers ending in 5 round up?

The rule generally told to 7-year-olds is that numbers ending in 1-4 are rounded down, while numbers ending in 5-9 are rounded up (numbers ending in 0 aren't rounded at all). This is a bit of an arbitrary rule - there are 9 numbers (1-9) that are rounded, and 5 is directly in the middle of them.


1 Answers

First off, in most languages an undecorated constant like "1.55" is treated as a double precision value. However, 1.55 is not exactly representable as double precision value, because it doesn't have a terminating representation in binary. This causes many curious behaviors, but one effect is that when you type 1.55, you don't actually get the value that's exactly halfway between 1.5 and 1.6.

In binary, the decimal number 1.55 is:

1.10001100110011001100110011001100110011001100110011001100110011001100... 

When you type "1.55", this value actually gets rounded to the nearest representable double-precision value (on many systems... but there are exceptions, which I'll get to). This value is:

1.1000110011001100110011001100110011001100110011001101 

which is slightly larger than 1.55; in decimal, it's exactly:

1.5500000000000000444089209850062616169452667236328125 

So, when asked to round this value to a single digit after the decimal place, it will round up to 1.6. This is why most of the commenters have said that they can't duplicate the behavior that you're seeing.

But wait, on your system, "1.55" rounded down, not up. What's going on?

It could be a few different things, but the most likely is that you're on a platform (probably Windows), that defaults to doing floating-point arithmetic using x87 instructions, which use a different (80-bit) internal format. In the 80-bit format, 1.55 has the value:

1.100011001100110011001100110011001100110011001100110011001100110 

which is slightly smaller than 1.55; in decimal, this number is:

1.54999999999999999995663191310057982263970188796520233154296875 

Because it is just smaller than 1.55, it rounds down when it is rounded to one digit after the decimal point, giving the result "1.5" that you're observing.

FWIW: in most programming languages, the default rounding mode is actually "round to nearest, ties to even". It's just that when you specify fractional values in decimal, you'll almost never hit an exact halfway case, so it can be hard for a layperson to observe this. You can see it, though, if you look at how "1.5" is rounded to zero digits:

>>> "%.0f" % 0.5 '0' >>> "%.0f" % 1.5 '2' 

Note that both values round to even numbers; neither rounds to "1".

Edit: in your revised question, you seem to have switched to a different python interpreter, on which floating-point is done in the IEEE754 double type, not the x87 80bit type. Thus, "1.55" rounds up, as in my first example, but "5.55" converts to the following binary floating-point value:

101.10001100110011001100110011001100110011001100110011 

which is exactly:

5.54999999999999982236431605997495353221893310546875 

in decimal; since this is smaller than 5.55, it rounds down.

like image 199
Stephen Canon Avatar answered Sep 21 '22 01:09

Stephen Canon