Search code examples
pythonblender

Formulating the "close enough to zero" condition


I'm doing calculations with 3D vectors with floating point coordinates. Occasionally, I want to check if a vector is nonzero. However, with floating point numbers, there's always a chance of a rounding error.

Is there a standard way in Python to check if a floating point number is sufficiently close to zero? I could write abs(x) < 0.00001, but it's the hard-coded cutoff that bugs me on general grounds ...


Solution

  • Like Ami wrote in the comments, it depends on what you're doing. The system epsilon is good for single operation errors, but when you use already rounded values in further calculations, the errors can get much larger than the system epsilon. Take this extreme example:

    import sys
    print('%.20f\n' % sys.float_info.epsilon)
    x = 0.1
    for _ in range(25):
        print('%.20f' % x)
        x = 11*x - 1
    

    With exact values, x would always be 0.1, since 11*0.1-1 is 0.1 again. But what really happens is this:

    0.00000000000000022204
    
    0.10000000000000000555
    0.10000000000000008882
    0.10000000000000097700
    0.10000000000001074696
    0.10000000000011821655
    0.10000000000130038202
    0.10000000001430420227
    0.10000000015734622494
    0.10000000173080847432
    0.10000001903889321753
    0.10000020942782539279
    0.10000230370607932073
    0.10002534076687252806
    0.10027874843559780871
    0.10306623279157589579
    0.13372856070733485367
    0.47101416778068339042
    4.18115584558751685051
    44.99271430146268357930
    493.91985731608951937233
    5432.11843047698494046926
    59752.30273524683434516191
    657274.33008771517779678106
    7230016.63096486683934926987
    79530181.94061353802680969238
    

    Note that the original x differed from 0.1 by far less than my system epsilon, but the error quickly grew larger than that epsilon and even your 0.00001 and now it's in the millions.

    This is an extreme example, though, and it's highly unlikely you'll encounter something this bad. But it shows that the precision really depends on what you're doing, so you'll have to find a good way for your particular calculation.