2014-02-08 4 views
5

Код ниже (для вычисления подобия косинуса) при повторном запуске на моем компьютере выводит 1.0, 0.9999999999999998 или 1.0000000000000002. Когда я вывожу нормализованную функцию, она вернет только 1.0. Я думал, что операции с плавающей запятой должны быть детерминированными. Что может быть причиной этого в моей программе, если одни и те же операции применяются к тем же данным на одном компьютере каждый раз? Может быть, это что-то связано с тем, где в стеке вызывается функция нормализации? Как я могу это предотвратить?Дефектоскоп с плавающей запятой Python

#! /usr/bin/env python3 

import math 

def normalize(vector): 
    sum = 0 
    for key in vector.keys(): 
     sum += vector[key]**2 
    sum = math.sqrt(sum) 
    for key in vector.keys(): 
     vector[key] = vector[key]/sum 
    return vector 

dict1 = normalize({"a":3, "b":4, "c":42}) 
dict2 = dict1 

n_grams = list(list(dict1.keys()) + list(dict2.keys())) 
numerator = 0 
denom1 = 0 
denom2 = 0 

for n_gram in n_grams: 
    numerator += dict1[n_gram] * dict2[n_gram] 
    denom1 += dict1[n_gram]**2 
    denom2 += dict2[n_gram]**2 

print(numerator/(math.sqrt(denom1)*math.sqrt(denom2))) 

ответ

11

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

Когда вы вызываете .keys(), порядок получаемого списка потенциально случайный.

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

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

+0

Порядок словаря не является детерминированным в Python 3.x, если явно не установлен в Python 2.x – thefourtheye

+0

Итак, вы бы рекомендовали выполнить заказ или просто оставить его в категории «с плавающей запятой» точно, хорошо? Все, что я собираюсь делать, это наблюдать за этими данными. Не могли бы вы изменить свой ответ, если эти данные будут использоваться в вычислениях дальше по строке? –

+2

Я бы просто оставил его в области с плавающей точкой, а не в точном. – Amber

Смежные вопросы