Вы работаете с объектами NumPy float64
вместо Python float
объектов. Это имеет несколько последствий:
На Python 3, float64
объектов закруглены с использованием Numpy округления коды вместо языка Python. Код округления Python для float
s всегда дает правильно округленные результаты. Код округления NumPy не работает. (В Python 2 переопределить операцию round
для настраиваемых типов невозможно, поэтому, когда вы округляете объект float64
в Python 2, он сначала преобразуется в Python float
, а затем код округления Python используется для получения результата float
. является основной причиной того, что вы видите разницу между Python 2 и Python 3.)
снова на Python 3, из вышеизложенного, round
на float64
дает float64
результат. На Python 2, round
на объекте float64
появляется результат float
.
Python float
Объекты имеют разные repr
, что даст выходной сигнал pleasanter. В частности, поплавок Python repr
гарантирует округление в течение (не слишком больших, не слишком малых) десятичных значений с не более чем 15 значащими цифрами: например, 0.58
- '0.58'
. Представление объектов NumPy float64
не имеет этого свойства: оно просто распечатывает результат на основе наиболее значимых 17 десятичных цифр хранимого значения.
Так что, если вам конвертировать значения в Python float
объектов до раунда, вы увидите приятней выход (а в некоторых случаях результаты могут быть чуть-чуть более точными). Но обратите внимание, что только потому, что вывод выглядит неплохо, это не значит, что результаты, которые вы получаете, точны. Ничто из этого не меняет того факта, что 0.58
не, точно представляемый как Python float
(или действительно NumPy float64
, который использует тот же формат). Помните, что с бинарной точкой с плавающей точкой, что вы видите, не то, что вы получаете.
Некоторых примеров вывод на Python 3:
>>> random_nums = np.array([-1, 0, 1, 2, 3])
>>> probabilities = np.array([0.01, 0.3, 0.58, 0.1, 0.01])
>>> target = dict(zip(random_nums, probabilities))
>>> {k: round(v, 2) for k, v in target.items()}
{0: 0.29999999999999999, 1: 0.57999999999999996, 2: 0.10000000000000001, 3: 0.01, -1: 0.01}
>>> {k: round(float(v), 2) for k, v in target.items()}
{0: 0.3, 1: 0.58, 2: 0.1, 3: 0.01, -1: 0.01}
Если вам нужно точное округление с поплавками/дублями, сделать округление при преобразовании в строку для вывода. Из-за количества отображаемых цифр это близко, так как выбранная точность с плавающей запятой достигает этих чисел. –