Почему правила кастования различаются между компьютерами в python?
Я запускаю python 2.7 на своем Mac, и я работаю над проектом группового кодирования с другими людьми, использующими Ubuntu. Каждый раз, когда код, который они пишут, не будет работать на моем компьютере из-за ошибок правила каста:
273 # Apply column averages to image
--> 274 img[:middle] *= (bg[0]/np.tile(topCol, (middle,1)))
275 img[middle:] *= bg[1]/np.tile(botCol, (middle,1))
276
TypeError: Cannot cast ufunc multiply output from dtype('float64') to dtype('int16') with casting rule 'same_kind'
Я не думаю, что вам нужна специфика, так как это происходит в нескольких разных местах с разными типами номеров.
Он работает на всех своих компьютерах без проблем. Все, что я пишу, работает для них, но каждый так часто, что они пишут, не работает для меня.
Есть ли причина, по которой наши машины не согласны, и есть ли способ изменить ситуацию на моем конце?
Спасибо!
Ответы
Ответ 1
Этот поток говорит о том, что ваш numpy
новее, чем версия, которую используют ваши коллеги (пожалуйста, используйте numpy.version.version
). В ветке разработки 1.7.0 кажется, что они изменили правило неявного каста на более строгое правило same_kind
, которое запрещает (между прочим) отличать между форматами с плавающей запятой и целым числом.
Чтобы обойти это, я бы рекомендовал использовать такой код:
img[:middle] *= (bg[0]/np.tile(topCol, (middle,1))).astype(img.dtype)
Ответ 2
У nneonneo было правильное решение, я подумал, что добавлю несколько других работ.
Одна из проблем заключалась в том, что переменная img
была определена вручную ранее как int
. Тогда умножение с a float
нарушает строгий тип литья
img = np.int16( cp.deepcopy(imgArray) )
...
img[:middle] *= bg[0]/np.tile(topCol, (middle,1))
>>TypeError: Cannot cast ufunc multiply output from dtype('float64') to dtype('int16') with casting rule 'same_kind'
Одна работа вокруг:
Я могу изменить начальное определение типа переменной, чтобы соответствовать тому, что нужно позже:
img = np.float64( cp.deepcopy(imgArray) )
...
img[:middle] *= bg[0]/np.tile(topCol, (middle,1))
Или я могу сохранить оригинальный тип кастинга и изменить оператор:
img = np.int16( cp.deepcopy(imgArray) )
...
img[:middle] = img[:middle]*bg[0]/np.tile(topCol, (middle,1))
По какой-то причине Numpy разрешает операцию таким образом, где она не будет с *=
Спасибо за помощь!
Ответ 3
Чтобы процитировать разработчиков numpy (http://docs.scipy.org/doc/numpy-dev/release.html):
Отливка по умолчанию для операций inplace изменилась на "same_kind". Например, если n является массивом целых чисел, а f является массивом поплавков, то n + = f приведет к типу TypeError, тогда как в предыдущих версиях Numpy поплавки будут беззвучно передаваться в int. В маловероятном случае, когда примерный код не является фактической ошибкой, он может быть обновлен обратно совместимым способом, переписав его как np.add(n, f, out = n, casting = 'unsafe'). Старое "небезопасное" значение устарело, поскольку Numpy 1.7.
Таким образом, если вы хотите сохранить умножение inplace, код будет выглядеть следующим образом:
np.multiply(img[:middle], (bg[0]/np.tile(topCol, (middle,1))), out=img[:middle], casting='unsafe')