Подтвердить что ты не робот

Почему правила кастования различаются между компьютерами в 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'

Я не думаю, что вам нужна специфика, так как это происходит в нескольких разных местах с разными типами номеров.

Он работает на всех своих компьютерах без проблем. Все, что я пишу, работает для них, но каждый так часто, что они пишут, не работает для меня.

Есть ли причина, по которой наши машины не согласны, и есть ли способ изменить ситуацию на моем конце?

Спасибо!

4b9b3361

Ответ 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')