2

I have to find smallest positive number (which doesn't equal to 0) and save it to variable "small" and largest positive number which is less than infinity (math.inf) and save it to variable "great". My code looks so far like this:

x = float(1)
import math 

small = x/2
while small > 0:
    small = small/2
    print(small)

y = float(1)    
great = y*2
while great < math.inf:
    great = great*2
    print(great)

It prints list of numbers but the problem is that Python saves "small= 0" and "great= inf". How can I save required numbers without having to manually input them from the list which I get from my code?

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
Pytstud
  • 55
  • 3
  • Can you share what output you're getting after running above code? – Harshit Oct 11 '18 at 06:49
  • Why do you expect `small` do *not* be `0` if your while condition is `while small > 0`? Either `small` will be `<= 0` or you will have an infinite loop. Since `small` can never be `< 0`, the options are it will be `== 0` (it will actually be very, very close to `0`, not `0`) or you will have an infinite loop. – DeepSpace Oct 11 '18 at 06:52
  • Related: https://stackoverflow.com/questions/588004/is-floating-point-math-broken – DeepSpace Oct 11 '18 at 06:54
  • Also, what "list" are you referring to? there's no list in your code. – DeepSpace Oct 11 '18 at 06:57
  • edited my answer, provided better solution. – Vaibhav Vishal Oct 11 '18 at 07:44

2 Answers2

1
x = float(1)    
small = x

while small > 0:
    real_small = small
    small = small/2
print(small) # 0.0
print(real_small) # 5e-324

This will get you smallest possible(almost) float. Hope you can now figure out largest too similarly.

The best and easiest solution for finding smallest and largest possible float is:

import numpy as np
import math

>>> # Smallest
>>> np.nextafter(0, 1)
5e-324


>>> # Largest
>>> np.nextafter(math.inf, 0)
1.7976931348623157e+308
>>> np.nextafter(np.float64(math.inf), 0)
1.7976931348623157e+308

Another solution is using sys.float_info:

>>> import sys
>>> sys.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)

All methods provides same max value, but for min value sys.float_info provides different value than others, I am not sure why, maybe someone else can enlighten me regarding this.

nextafter(x, y) source
The nextafter(), nextafterf(), and nextafterl() functions return the next representable floating-point value following x in the direction of y.

If y is less than x, these functions will return the largest representable number less than x.

If x equals y, the functions return y.

numpy.nextafter(x1, x2, /, out=None, *, where=True, casting='same_kind', order='K', dtype=None, subok=True[, signature, extobj]) = < ufunc 'nextafter'> source
Return the next floating-point value after x1 towards x2, element-wise.

Vaibhav Vishal
  • 6,576
  • 7
  • 27
  • 48
1

You should break the first loop before small becomes 0, and the second loop before great is equal to infinity:

import math

small = 1
while True:
    if small / 2 == 0:
        print(small)
        break
    small /= 2

great = float(1)
while True:
    if great * 2 == math.inf:
        print(great)
        break
    great *= 2

This outputs:

5e-324
8.98846567431158e+307
blhsing
  • 91,368
  • 6
  • 71
  • 106