On 18Dec2022 18:35, Paul St George <em...@paulstgeorge.com> wrote:
So I am working on a physics paper with a colleague. We have a theory about 
Newtons Cradle. We answer the question why when you lift and drop balls 1 and 
2, balls 4 and 5 rise up. I could say more, but ... (if you are interested 
please write to me).

We want to illustrate the paper with animations. The theory includes distortion 
of the balls and this distortion is very very small. So, I am sent data with 
locations and dimensions to 13 decimal places. Something strange is happening 
with the animations: the balls are not moving smoothly. I do not know (yet) 
where the problem lies so it is difficult to provide a clear narrative.

Because there is a problem, I am investigating in all areas. This brings me to 
the question I asked here. I am not expecting six decimal places or three 
decimal places to be as accurate as thirteen decimal places, but I would like 
to be in control of or fully aware of what goes on under the bonnet.

First the short take: your machine pobably is quite precise, and float is far more performant that the other numeric types available. Your source data seem to have more round off than the rounding in a float.

Under the bonnet:

A Python float is effectively a base-2 value in scientific notation. Internally it has a base-2 mantissa and base-2 exponent. This page:
https://docs.python.org/3/library/stdtypes.html#typesnumeric
says that CPython's float uses C's "double" floating point type
(you are almost certainly using the CPython implementation) and thus you're using the machine's floating point implemenetation.

I believe that almost all modern CPUs implement IEEE 754 floating point:
https://en.wikipedia.org/wiki/IEEE_754

Because they're base 2, various values in other bases will not be precisely representable as a float. For example, 1/3 (which you will know is _also_ not representable precisely as a base-10 value such as 0.333).

You can get specifics of your Python's floating point from `sys.float_Info`, i.e:

    from sys import float_info

The look at float_info.epsilon etc. Details:
https://docs.python.org/3/library/sys.html#sys.float_info

Here's my machine:

Python 3.10.6 (main, Aug 11 2022, 13:47:18) [Clang 12.0.0 (clang-1200.0.32.29)] on darwin Type "help", "copyright", "credits" or "license" for more information.
    >>> from sys import float_info
    >>> float_info
sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)

Values of note: mant_dig=53 (53 base-2 bits), dig=15 (15 decimal digits of precision).

You might want to look at sys.float_repr_style here:
https://docs.python.org/3/library/sys.html#sys.float_repr_style
which affects how Python writes floats out. In particular this text:

If the string has value 'short' then for a finite float x, repr(x) aims to produce a short string with the property that float(repr(x)) == x. This is the usual behaviour in Python 3.1 and later.

Again, on my machine:

    >>> 64550.727
    64550.727
    >>> 64550.728
    64550.728
    >>> 64550.72701
    64550.72701
    >>> 64550.7270101
    64550.7270101
    >>> 64550.727010101
    64550.727010101
    >>> 64550.72701010101
    64550.72701010101
    >>> 64550.7270101010101
    64550.72701010101
    >>> 64550.727010101010101
    64550.72701010101
    >>> 64550.72701010101010101
    64550.72701010101

On 17 Dec 2022, at 16:54:05 EST 2022, Thomas Passin wrote:
On 12/17/2022 3:45 PM, Paul St George wrote:
Thanks to all!
It was the rounding rounding error that I needed to avoid (as Peter J. Holzer 
suggested). The use of decimal solved it and just in time. I was about to 
truncate the number, get each of the characters from the string mantissa, and 
then do something like this:

64550.727

64550 + (7 * 0.1) + (2 * 0.01) + (7 * 0.001)

Now I do not need to!

Good, because if you do that using floats it will be less precise than float(64550.727). (Which I see Alan has already stated.)

Your source file contains strings like "64550.727". They look to already be less than 13 digits of precision as written i.e. some round off already took place when that file was written. Do you know the precision of the source data?

I suspect that rather than chasing a "perfect" representation of your source data, which is already rounded off, you:
- see if the source values can be obtained more precisely
- figure out which operations in your simulation contribute to the motion roughness you see

I'm no expert on floating point coding for precision, but I believe that trying to work with values "close together" in magnitude is important because values of different scales inherently convert one of them to the other scale (i.e. similar sized exponent part) with corresponding loss of precision in the mantissa part. That may require you to form your calcutations carefully.

See if you can locate a source for the jerkiness (by printing intermediate results) and then maybe rephrase that step?

Cheers,
Cameron Simpson <c...@cskk.id.au>
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to