Decimal-fraction precision question
Decimal-fraction precision question
These two lines:
my_string = str(-0.3470) #Test value
basic.show_string(my_string)
yield the string "-0.347". That trailing zero is important in science and engineering because it indicates accuracy. For example, 0.3 mm is not the same as 0.30 mm. The latter indicates accuracy to a hundredth of a mm. So, it seems MakeCode saves the original value as -0.347, not as -0.3470.
Does MicroPython have a way to set the precision of a floating-point number so the trailing zero becomes part of the value and thus part of the string? Thanks. Happy July 4th. --Jon
my_string = str(-0.3470) #Test value
basic.show_string(my_string)
yield the string "-0.347". That trailing zero is important in science and engineering because it indicates accuracy. For example, 0.3 mm is not the same as 0.30 mm. The latter indicates accuracy to a hundredth of a mm. So, it seems MakeCode saves the original value as -0.347, not as -0.3470.
Does MicroPython have a way to set the precision of a floating-point number so the trailing zero becomes part of the value and thus part of the string? Thanks. Happy July 4th. --Jon
Re: Decimal-fraction precision question
Sadly, no. I don't know of any (non-symbolic¹) programming language that retains that concept. I haven't seen the "trailing zeros indicate retained precision" convention since I was in grammar school in the 1980s and I've been a mechanical engineer for most of the time since then.
Because of the way that MicroPython stores floating point numbers, it can't even store '-0.3470' exactly. It's probably storing something closer in value to -0.34700000286102294921875 (the four bytes 0xbeb1a9fc: see IEEE-754 Floating Point Converter for details). The vast majority of computer systems work this way.
Most MicroPython ports have integer precision limited only by available memory. If you wish to retain precision, you could store numbers as ratios of two integers: something like -3470 / 10000. Unfortunately, you'd have to write all the code to ensure that all the calculations were done correctly, for as soon as it hits floating point, it's back to weird binary rounding again. The two Python data types that might help here — Decimal and Fraction — are not available for MicroPython.
If you're asking how to represent that number of decimal places, there are various ways to format floating point numbers, such as:
but note that this is simple rounding:
---
¹: such as maple, mathematica, maxima, etc. I suspect that the charmingly niche language Frink might retain trailing zeros, as it's the sort of thing it would do.
Because of the way that MicroPython stores floating point numbers, it can't even store '-0.3470' exactly. It's probably storing something closer in value to -0.34700000286102294921875 (the four bytes 0xbeb1a9fc: see IEEE-754 Floating Point Converter for details). The vast majority of computer systems work this way.
Most MicroPython ports have integer precision limited only by available memory. If you wish to retain precision, you could store numbers as ratios of two integers: something like -3470 / 10000. Unfortunately, you'd have to write all the code to ensure that all the calculations were done correctly, for as soon as it hits floating point, it's back to weird binary rounding again. The two Python data types that might help here — Decimal and Fraction — are not available for MicroPython.
If you're asking how to represent that number of decimal places, there are various ways to format floating point numbers, such as:
Code: Select all
print('%.4f' % -0.3470 )
-0.3470
Code: Select all
print('%.4f' % -0.34758 )
-0.3476
¹: such as maple, mathematica, maxima, etc. I suspect that the charmingly niche language Frink might retain trailing zeros, as it's the sort of thing it would do.
Re: Decimal-fraction precision question
Thank you very much for your insight. The information you provided is very helpful and appreciated. Happy July 4th.
- pythoncoder
- Posts: 5956
- Joined: Fri Jul 18, 2014 8:01 am
- Location: UK
- Contact:
Re: Decimal-fraction precision question
Alternatively (which I find more readable than the string modulus operator):
The 3 guarantees that three digits will be printed to the right of the decimal point, yielding "0.300". This is the same pretty formatting by a different means and does not contradict the above observations about stored precision.
Code: Select all
print('{:6.3f}'.format(0.3))
Peter Hinch
Index to my micropython libraries.
Index to my micropython libraries.
Re: Decimal-fraction precision question
Yes, .format() is probably more readable and recommended these days. I stick to the first thing I learned, so I'm perpetually annoyed that few languages support the one true FORTRAN codes ...
Thinking out loud (= ‘uh-oh, he has no idea what he's doing’) I wonder if working with numbers as strings might help? Entering a literal
on the source will lose any trailing zeroes, but entering
will retain them. If there is a decimal point in the string s, len(s) - (s.find('.')+1) returns the number of decimal places in the string.
I don't know how to do this with .format(), and this is a not-remotely-useful outline of how to get data-defined precision in MicroPython, but something like:
would reconstruct your numeric string exactly.
Just be careful to remember that Python numbers-as-strings don't do what you might expect, but rather what you'd suspect: s+s returns the rather hilarious '-0.3470-0.3470' instead of the more sensible -0.694
Thinking out loud (= ‘uh-oh, he has no idea what he's doing’) I wonder if working with numbers as strings might help? Entering a literal
Code: Select all
s=-0.3470
Code: Select all
s="-0.3470"
I don't know how to do this with .format(), and this is a not-remotely-useful outline of how to get data-defined precision in MicroPython, but something like:
Code: Select all
print("%*.*f" % (len(s),
len(s) - (s.find('.')+1),
float(s)))
Just be careful to remember that Python numbers-as-strings don't do what you might expect, but rather what you'd suspect: s+s returns the rather hilarious '-0.3470-0.3470' instead of the more sensible -0.694
- pythoncoder
- Posts: 5956
- Joined: Fri Jul 18, 2014 8:01 am
- Location: UK
- Contact:
Re: Decimal-fraction precision question
One way to write programmatic format specifiers:
Code: Select all
x = 5
y = 3
print('{val:{wid}.{dec}f}'.format(val=0.3, wid=x, dec=y))
Peter Hinch
Index to my micropython libraries.
Index to my micropython libraries.
Re: Decimal-fraction precision question
🤯 TIL!pythoncoder wrote: ↑Tue Jul 06, 2021 5:57 amOne way to write programmatic format specifiers:Code: Select all
x = 5 y = 3 print('{val:{wid}.{dec}f}'.format(val=0.3, wid=x, dec=y))
Re: Decimal-fraction precision question
The OP hasn't checked in since July, but this might have been useful for them: DecimalNumber: floating point arithmetic with arbitrary precision for micropython. It would still require some work to keep track of the trailing zero precision convention, though.