0

I'm new to Cython, and have made a mean.pyx file with

#cython: language_level=3

def cmean(list arr, int length):
    cdef float tot
    cdef float elem
    tot = 0
    for i in range(length):
        elem = arr[i]
        tot += elem
    tot /= length
    return tot

I then call this from a Python file main.py:

import pyximport

pyximport.install()

from mean import cmean


arr = [1,2,4]
cres = cmean(arr, len(arr))
pyres = sum(arr)/len(arr)
print(cres)
print(pyres)
print(cres == pyres)

which outputs

2.3333332538604736
2.3333333333333335
False

Why are the results not the same?

I'm using Cython==0.29.30 and Python 3.9.2

ignoring_gravity
  • 6,677
  • 4
  • 32
  • 65
  • 1
    it should be ```cdef double tot``` – Nin17 Jun 19 '22 at 10:15
  • perfect, now it works as expected - thanks! – ignoring_gravity Jun 19 '22 at 10:42
  • `double` also doesn't guarantee that the numbers are the same, it just makes any differences smaller. Floating point numbers are a little imprecise. – DavidW Jun 19 '22 at 13:20
  • 1
    https://stackoverflow.com/questions/588004/is-floating-point-math-broken – DavidW Jun 19 '22 at 13:21
  • 1
    this is common problem with `float`/`double` in many languages. Even in Python you can see problem `0.1 + 0.2 == 0.3` gives `False` – furas Jun 19 '22 at 15:36
  • sure, but `.1 + .2` is really close to `.3` in that example, whilst here the error was a lot larger than I would've expected – ignoring_gravity Jun 19 '22 at 18:57
  • @DavidW how doesn't it guarantee that the numbers are the same? the problem was that ```float``` in c is 32-bit and ```float``` in python is 64-bit which is equivalent to the 64-bit ```double``` in c? – Nin17 Jun 20 '22 at 21:41
  • @Nin17 It's probably unlikely to be different in this case because there aren't too many other ways to express it. But suppose `sum` iterated backwards for some reason - that could end up being a slightly different number. It doesn't take much of a change for `==` to fail. – DavidW Jun 21 '22 at 03:33
  • @DavidW I'm not sure I follow. Surely the sum of the 64 bit representation of the numbers is the same whichever way you sum them? Can you give an example where it isn't because doing your reversed suggestion gives ```True```. – Nin17 Jun 21 '22 at 09:29
  • @Nin17 `numbers = [1e300, -1e300, 1]`. `sum(numbers)` is 1. `sum(reversed(numbers))` is 0 – DavidW Jun 21 '22 at 09:31
  • @Nin17 or `numbers = [0.1, 0.2, 0.7]` gives `1.0` and `0.9999999999999999` – DavidW Jun 21 '22 at 09:34
  • @DavidW ok fair enough – Nin17 Jun 21 '22 at 09:34

0 Answers0