Python Forum
f-strings round float down too much
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
f-strings round float down too much
#1
Output:
lt2a/forums /home/forums 4> cp -ft. /home/phil/foo.py '/home/phil/foo.py' -> './foo.py' removed './foo.py' lt2a/forums /home/forums 5> cat foo.py from decimal import Decimal from numpy import nextafter a = nextafter(0.0,1) d = Decimal(a) print('a =',a) print('d =',d) print('a =',repr(a)) print(f'a = {a}') print(f'd = {d}') print(f'a = {a!r}') lt2a/forums /home/forums 6> python3.6 foo.py a = 4.94065645841e-324 d = 4.940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625E-324 a = 4.9406564584124654e-324 a = 5e-324 d = 4.940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625E-324 a = 4.9406564584124654e-324 lt2a/forums /home/forums 7>
so, maybe it's fixed in 3.10.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#2
There are at least two different strategies for representing 64-bit IEEE floating point values as a decimal string that round-trip. In other words, they guarantee that x == float(str(x)). One choice is to return 17 digits of decimal precision. The second choice is to return the shortest possible string that converts back to the original number.

You are seeing both results. Both of the string representations represent the same binary value.

>>> float('5e-324') == float('4.9406564584124654e-324')
True
Now is gets complicated.

Python used to return a 17 digit string with trailing "0"s removed for repr(float) and a 12 digit string for str(float). The original distinction between str and repr was (roughly) that str was a user-friendly representation and repr was an exact representation. Around the Python 2.4/2.5 era, str was modified to return the shortest possible representation. As part of the development of Python 3, the shortest representation was used for both str and repr. IIRC, Python 2.6 also adopted the shortest representation.

In Python 3.6, shortest representation is used for both str and repr. Since the math module didn't have 'nextafter', I created the number using the hex value. You used numpy instead.

>>> a=float.fromhex('0x0.0000000000001p-1022')
>>> str(a)
'5e-324'
>>> repr(a)
'5e-324'
>>> print(f'a={a}')
a=5e-324
I don't know which version of numpy you're using, but recent versions follow Python current behavior. Since the numpy.float64 type uses its own versions of str and repr, can you repeat your example using a=float(nextafter(0.0,1). I'm guessing it will behave differently.
Reply
#3
casevh Wrote:Around the Python 2.4/2.5 era, str was modified to return the shortest possible representation.
In Python 2.7 in my Ubuntu machine, it works differently
>>> # python 2.7
>>> s = repr(1/3.4)
>>> t = str(1/3.4)
>>> s
'0.29411764705882354'
>>> t
'0.294117647059'
>>> float(s) == float(t)
False
That said, I don't understand Skaperen's bug report. What is exactly wrong?
Reply
#4
You are correct. My memory is a bit hazy.

Looking at this again, I'm not exactly sure what is the bug....
Reply
#5
the "bug" (i often don't know what the intentions are) is that i get the 12 digit result when printing a line the "old" way, which is a lot of function arguments with float as-is where there is a number, and i get a "shortest" for {variable_name} in an f-string. IOW, i can't simply convert all my old style print() calls to f-strings.

the version of numpy doesn't really matter. you can reproduce the number many ways, such as in post #2, and avoid numpy completely. did numpy calculate the correct number? from the hex result it looks like it did. but even if it did not, we have a reproducible number that f-string formats differently than expected.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#6
i've been think a lot about how i use numbers in life. i now realize i don't generally need them to be in decimal in most cases. i'm thinking i should just switch my life to hexadecimal. it's not hard to do in Python.

fyi, if you do, too, i recommend to not try to convert numbers to decimal to use them. just use them as they are. is 0xa90 < 0x9f0 True or False? did you need decimal to figure that out?

decimal is such a hassle.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  print a list strings is fast but printing the joined strings is slow Skaperen 9 3,913 Aug-26-2019, 07:48 PM
Last Post: Skaperen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020