Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZeroDivisionError when getting the __repr__ if nominal value is too small #135

Closed
OceanNuclear opened this issue Jan 21, 2021 · 5 comments · Fixed by #290
Closed

ZeroDivisionError when getting the __repr__ if nominal value is too small #135

OceanNuclear opened this issue Jan 21, 2021 · 5 comments · Fixed by #290

Comments

@OceanNuclear
Copy link
Contributor

OceanNuclear commented Jan 21, 2021

Perhaps this is a very obscure bug but it does exist.

When running the following block of code:

n, s = 1.1E-323, 0
v = uncertainties.core.Variable(n, s)
print(v)

It will throw a ZeroDivisionError at the print line.

I understand this is because, when converting the variable into a string using v.__repr__() it will attempt to factorize out the 1E-323 from both the v.n and the v.s.

It seems that python would only complain about division by zero when n is between [2.5E324, 12.5E324), making it a very specific and obscure problem, which is perhaps why I'm the first person to file an issue for it
I was working with a large enough dataset to hit upon this weird bug.

I know a few ways to workaround this problem on my own (choose all values <12.5E-324 and then set them to zero); but do you think there's a way to write the __repr__ in such a way to avoid future occurrences of this?

Side note:
Interestingly while testing the behaviour, I found out that python rounds all numbers above 2.5E-324 to the nearest multiple of 5E-324. I guess this is the resolution of IEEE-754 numbers?

@lebigot
Copy link
Collaborator

lebigot commented Jan 22, 2021

Wow, interesting.

Thanks for the concise but detailed report. A short traceback could be useful too, if you can add one.

I am not close to a computer, but I'll have a look soon: I don't like surprising behaviors. :)

@OceanNuclear
Copy link
Contributor Author

Oh right, certainly. Here's the traceback.

---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-3-d6c1535c9ec8> in <module>
----> 1 print(v)

~/miniconda3/envs/canary/lib/python3.8/site-packages/uncertainties/core.py in __str__(self)
   1841         # string
   1842         # (http://docs.python.org/2/library/string.html#format-specification-mini-language):
-> 1843         return self.format('')
   1844 
   1845     def __format__(self, format_spec):

~/miniconda3/envs/canary/lib/python3.8/site-packages/uncertainties/core.py in format(*args, **kwargs)
   2314         """)
   2315     def format(*args, **kwargs):
-> 2316         return args[0].__format__(*args[1:], **kwargs)
   2317 
   2318     def std_score(self, value):

~/miniconda3/envs/canary/lib/python3.8/site-packages/uncertainties/core.py in __format__(self, format_spec)
   2235             factor = 10.**common_exp
   2236 
-> 2237             nom_val_mantissa = nom_val/factor
   2238             std_dev_mantissa = std_dev/factor
   2239             # Limit for the last digit of the mantissas:

ZeroDivisionError: float division by zero

it happens inside the AffineScalarFunc.__format__ method.

@ArnaudPel
Copy link

We stumbled upon the same issue recently (uncertainties=3.2.2).

@lebigot
Copy link
Collaborator

lebigot commented Mar 5, 2025

I'm not working on this project anymore, but there are new, active maintainers, who hopefully can look at this, but from the look of it, I'm wondering if the values that the code is manipulating aren't very small (close to underflow).

If you have a minimal example that can reproduce this, that could help.

Otherwise, just exploring this possibility (very negative common_exp) could be useful.

@ArnaudPel
Copy link

ArnaudPel commented Mar 6, 2025

The original example provided at the beginning of the issue still raises a ZeroDivisionError, here is another one:

from uncertainties import ufloat
a = 1e-324
b = 3e-324
assert a < b
print(ufloat(a, 0.0))  # OK
print(ufloat(b, 0.0))  # ZeroDivisionError
Traceback (most recent call last):
  File "tmp/sandbox.py", line 74, in <module>
    print(ufloat(b, 0.0))  # ZeroDivisionError
  File "lib/python3.10/site-packages/uncertainties/core.py", line 1772, in __str__
    return self.format('')
  File "lib/python3.10/site-packages/uncertainties/core.py", line 2256, in format
    return args[0].__format__(*args[1:], **kwargs)
  File "lib/python3.10/site-packages/uncertainties/core.py", line 2177, in __format__
    nom_val_mantissa = nom_val/factor
ZeroDivisionError: float division by zero

(Same outcome in python 3.12)

OceanNuclear added a commit to OceanNuclear/uncertainties that referenced this issue Mar 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants