Unexpected behaviour of math.floor, round and int functions (rounding)

Chris Angelico rosuav at gmail.com
Sat Nov 20 20:02:45 EST 2021


On Sun, Nov 21, 2021 at 11:39 AM Avi Gross via Python-list
<python-list at python.org> wrote:
>
> Can I suggest a way to look at it, Grant?
>
> In base 10, we represent all numbers as the (possibly infinite) sum of ten
> raised to some integral power.

Not infinite. If you allow an infinite sequence of digits, you create
numerous paradoxes, not to mention the need for infinite storage.

> 123 is 3 times 1 (ten to the zero power) plus
> 2 times 10 (ten to the one power) plus
> 1 times 100 (ten to the two power)
>
> 123.456 just extends this with
> 4 times 1/10 (ten to the minus one power) plus
> 5 times 1/100 (10**-2) plus
> 6 time 1/1000 (10**-3)
>
> In binary, all the powers are not powers of 10 but powers of two.
>
> So IF you wrote something like 111 it means 1 times 1 plus 1 times 2 plus 1
> times 4 or 7. A zero anywhere just skips a 2 to that power. If you added a
> decimal point to make 111.111 the latter part would be 1/2 plus 1/4 plus 1/8
> or 7/8 which combined might be 7 and 7/8. So any fractions of the form
> something over 2**N can be made easily and almost everything else cannot be
> made in finite stretches. How would you make 2/3 or 3 /10?

Right, this is exactly how place value works.

> But the opposite is something true. In decimal, to make the above it becomes
> 7.875 and to make other fractions of the kind, you need more and more As it
> happens, all such base-2 compatible streams can be made because each is in
> some sense a divide by two.
>
> 7/16 = 1/2 * .875 = .4375
> 7/32 = 1/2 * .4375 = .21875
>
> and so on. But this ability is a special case artifact caused by a terminal
> digit 5 always being able to be divided in tow to make a 25 a unit longer
> and then again and again. Note 2 and 5 are factors of 10.  In the more
> general case, this fails. In base 7, 3/7 is written easily as 0.3 but the
> same fraction in decimal is a repeating copy of .428571... which never
> terminates. A number like 3/7 + 4/49 + 5/343 generally cannot be written in
> base 7 but the opposite is also true that only a approximation of numbers in
> base 2 or base 10 can ever be written. I am, of course, talking about the
> part to the right of the decimal. Integers to the left can be written in any
> base. It is fractional parts that can end up being nonrepeating.

If you have a number with a finite binary representation, you can
guarantee that it can be represented finitely in decimal too.
Infinitely repeating expansions come from denominators that are
coprime with the numeric base.

> What about pi and e and the square root of 2? I suspect all of them have an
> infinite sequence with no real repetition (over long enough stretches) in
> any base! I mean an integer base, of course. The constant e in base e is
> just 1.

More than "suspect". This has been proven. That's what transcendental means.

I don't think "base e" means the same thing that "base ten" does.
(Normally you'd talk about a base e *logarithm*, which is a completely
different concept.) But if you try to work with a transcendental base
like that, it would be impossible to represent any integer finitely.

(Side point: There are other representations that have different
implications about what repeats and what doesn't. For instance, the
decimal expansion for a square root doesn't repeat, but the continued
fraction for the same square root will. For instance, 7**0.5 is
2;1,1,1,4,1,1,1,4... with an infinitely repeating four-element unit.)

> I think there have been attempts to use a decimal representation in some
> accounting packages or database applications that allow any decimal numbers
> to be faithfully represented and used in calculations. Generally this is not
> a very efficient process but it can handle 0.3 albeit still have no way to
> deal with transcendental numbers.

Fixed point has been around for a long time (the simplest example
being "work in cents and use integers"), but actual decimal
floating-point is quite unusual. Some databases support it, and REXX
used that as its only numeric form, but it's not hugely popular.

> Let me leave you with Egyptian mathematics. Their use of fractions, WAY BACK
> WHEN, only had the concept of a reciprocal of an integer. As in for any
> integer N, there was a fraction of 1/N. They had a concept of 1/3 but not of
> 2/3 or 4/9.
>
> So they added reciprocals to make any more complex fractions. To make 2/3
> they added 1/2 plus 1/6 for example.
>
> Since they were not stuck with any one base, all kinds of such combined
> fractions could be done but of course the square root of 2 or pi were a bit
> beyond them and for similar reasons.
>
> https://en.wikipedia.org/wiki/Egyptian_fraction

It's interesting as a curiosity, but it makes arithmetic extremely difficult.

> My point is there are many ways humans can choose to play with numbers and
> not all of them can easily do the same thing. Roman Numerals were (and
> remain) a horror to do much mathematics with and especially when they play
> games based on whether a symbol like X is to the left or right of another
> like C as XC is 90 and CX is 110.

Of course, there are myriad ways to do things. And each one has
implications. Which makes it even more surprising that, when someone
sits down at a computer and asks it to do arithmetic, they can't
handle the different implications.

ChrisA


More information about the Python-list mailing list