Values returned from Python function differ in caller and callee
Question:
Running the Python program
import sys
from bisect import bisect
import numpy as np
def insert_sorted(vec, x):
""" insert x in sorted numpy array vec. Return the insertion position
and the new list """
ipos = bisect(vec, x)
print("nexiting insert_sorted, len(vec), ipos, x =", len(vec), ipos, x)
return ipos, np.insert(vec, ipos, x)
def growing_pos(vec):
""" return the successive positions where the elements of vec would be inserted """
n = len(vec)
if n < 1:
return vec.astype(int)
vec_sorted = np.array([vec[0]])
ipos = np.zeros(shape=n, dtype=np.int8)
for i in range(n):
if i > 0:
ipos[i], vec_sorted = insert_sorted(vec_sorted, vec[i])
print("i, ipos[i], vec[i] =", i, ipos[i], vec[i])
if ipos[i] < 0: # debug
# print("vec_sorted =",vec_sorted)
sys.exit("in growing_pos, should not have ipos[i] < 0")
return ipos
np.random.seed(123)
vec = np.random.uniform(size=1000)
print(growing_pos(vec))
The program stops with
exiting insert_sorted, len(vec), ipos, x = 132 83 0.6006985678335899
i, ipos[i], vec[i] = 132 83 0.6006985678335899
exiting insert_sorted, len(vec), ipos, x = 133 120 0.8658644583032646
i, ipos[i], vec[i] = 133 120 0.8658644583032646
exiting insert_sorted, len(vec), ipos, x = 134 130 0.9835216092035556
i, ipos[i], vec[i] = 134 -126 0.9835216092035556
in growing_pos, should not have ipos[i] < 0
I don’t understand why at the end ipos
in insert_sorted()
does not equal ipos[i]
in growing_pos()
. Using bisect_left()
or bisect_right()
instead of bisect()
gives the same result.
Answers:
You are declaring your index array with 8-bit integers:
ipos = np.zeros(shape=n, dtype=np.int8)
8-bit integer can hold values from -128 to 127. You are trying to insert value 130, which overflows and becomes -126. Newer numpy
versions won’t allow that and will raise an exception.
Running the Python program
import sys
from bisect import bisect
import numpy as np
def insert_sorted(vec, x):
""" insert x in sorted numpy array vec. Return the insertion position
and the new list """
ipos = bisect(vec, x)
print("nexiting insert_sorted, len(vec), ipos, x =", len(vec), ipos, x)
return ipos, np.insert(vec, ipos, x)
def growing_pos(vec):
""" return the successive positions where the elements of vec would be inserted """
n = len(vec)
if n < 1:
return vec.astype(int)
vec_sorted = np.array([vec[0]])
ipos = np.zeros(shape=n, dtype=np.int8)
for i in range(n):
if i > 0:
ipos[i], vec_sorted = insert_sorted(vec_sorted, vec[i])
print("i, ipos[i], vec[i] =", i, ipos[i], vec[i])
if ipos[i] < 0: # debug
# print("vec_sorted =",vec_sorted)
sys.exit("in growing_pos, should not have ipos[i] < 0")
return ipos
np.random.seed(123)
vec = np.random.uniform(size=1000)
print(growing_pos(vec))
The program stops with
exiting insert_sorted, len(vec), ipos, x = 132 83 0.6006985678335899
i, ipos[i], vec[i] = 132 83 0.6006985678335899
exiting insert_sorted, len(vec), ipos, x = 133 120 0.8658644583032646
i, ipos[i], vec[i] = 133 120 0.8658644583032646
exiting insert_sorted, len(vec), ipos, x = 134 130 0.9835216092035556
i, ipos[i], vec[i] = 134 -126 0.9835216092035556
in growing_pos, should not have ipos[i] < 0
I don’t understand why at the end ipos
in insert_sorted()
does not equal ipos[i]
in growing_pos()
. Using bisect_left()
or bisect_right()
instead of bisect()
gives the same result.
You are declaring your index array with 8-bit integers:
ipos = np.zeros(shape=n, dtype=np.int8)
8-bit integer can hold values from -128 to 127. You are trying to insert value 130, which overflows and becomes -126. Newer numpy
versions won’t allow that and will raise an exception.