另一個Python浮點問題。我正在創建一個應用程序來幫助我們的培訓部門。這個應用程序的一部分是處理類的評估。評估包括一類設備,書面測試分數,操作測試分數和操作測試時間。這個承諾會很長。返回浮點數的Python方法爲相同的原始數據返回不同的值
有一個公式計算得分:眼下的界面允許用戶輸入測試分數和分和秒爲道路試驗
score = written_test + operational - best_decimal_time + decimal_time
percentage = score/best score
。從理論上講,最佳時間的得分爲:
written_test + operational
因爲小數點會抵消。
注意,written_test
是使用Django一個評估模型定義是的Evaluation
的student
屬性的屬性:
class Evaluation(models.Model):
student = models.ForeignKey(StudentRegistration)
machine_class = models.ForeignKey(MachineClass)
operational = models.IntegerField()
minutes = models.IntegerField(null=True, blank=True, default=0)
seconds = models.IntegerField(null=True, blank=True, default=0)
raw_time = models.CharField(max_length=5, null=True, blank=True, default=0)
decimal_time = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=True, blank=True)
score = models.DecimalField(max_digits=15, decimal_places=2, default=0, null=True, blank=True)
percent = models.DecimalField(max_digits=15, decimal_places=2, default=0, null=True, blank=True)
evaluator = models.ForeignKey(Instructor, null=True, blank=True, default=None)
的保存方法的評價是:
def save(self, *args, **kwargs):
"""Sets the raw_time and decimal_time from the minutes and seconds and saves the object."""
self.raw_time = self.get_raw_time()
self.decimal_time = self.get_decimal_time()
self.score = self.get_score()
super(Evaluation, self).save(*args, **kwargs)
get_raw_time方法:
def get_raw_time(self):
"""Formats the minutes and seconds into a time string d:dd and returns the formatted time."""
s = '0'
if self.seconds < 10:
s = s + str(self.seconds)
else:
s = self.seconds
return '%s:%s' % (self.minutes, s)
的get_decimal_time方法:
def get_decimal_time(self):
return '%.3f' % ((self.minutes) + (self.seconds/60.0))
的get_best_time方法:
def get_best_time(self):
reg_ary = []
s_class = self.student.scheduled_class_id
registrations = StudentRegistration.objects.filter(scheduled_class_id=s_class).values('id')
for r in registrations:
reg_ary.append(r['id'])
evaluations = Evaluation.objects.filter(student_id__in=reg_ary).order_by('decimal_time')
for e in evaluations:
if e.machine_class == self.machine_class:
if e.decimal_time < self.get_decimal_time():
return '%.3f' % round(e.decimal_time, 4)
else:
return '%.3f' % round(self.get_decimal_time(), 4)
return self.get_decimal_time()
最後get_score方法:
def get_score(self):
return '%.2f' % (Decimal(self.student.written_test) + Decimal(self.operational) -
Decimal(self.get_decimal_time()) + Decimal(self.get_best_time()))
這裏是數字:
written_test = 21
operational = 96
minutes = 3
seconds = 1
這是表格的第一個入口,所以它是最好的時間,所以當計算得分時應該是21 + 96 = 117
。
當我輸入這些號碼是我得到:
117 written to the database # correct maybe, I think it should be 117.00 but not huge.
raw_time = 3:01 # correct
decimal_time = 3.017 # correct
best_decimal_time = 3.017 # correct
score = 117.00 # correct
當我更改記錄爲2秒,我得到:
116.98 written to the database # incorrect, should still be 117
raw_time = 3:02 # correct
decimal_time = 3.033 # correct
best_decimal_time = 3.033 # correct
score = 117.00 # correct
當我刪除的記錄,並使用分鐘後重新啓動= 3和秒= 2 I得到:
117 written to the database # correct mostly
raw_time = 3:02 # correct
decimal_time = 3.033 # correct
best_decimal_time = 3.033 # correct
score = 117.00 # correct
最後,當我更改記錄到1秒我得到:
117.02 written to the database # incorrect, should still be 117
raw_time = 3:01 # correct
decimal_time = 3.017 # correct
best_decimal_time = 3.017 # correct
score = 117.00 # correct
這也正是每個值都來自:
I looked in the database for the value written there
raw_time = self.raw_time
decimal_time = self.decimal_time
best_decimal_time = self.get_best_time()
score = self.get_score()
我懷疑這是用浮漂的二進制表示的問題,但似乎無法弄清楚如何解決它。我曾嘗試投入到十進制,有些東西只是在某個地方,我的大腦傷害了一點。我知道這很長,但我想確保提供儘可能多的相關信息。難道是時間到了三位數的精度,而得分不是?
是困惑我的部分是數據庫越來越的get_score()
的結果被寫入到數據庫中的值,但什麼是顯示在界面是不同的。
對此提出建議?
差異0.02看起來比二進制浮點表示問題通常要大。 – Messa
這就是我最初想到的,但我無法得出更好的理由,爲什麼'get_score()'方法在編輯時只返回兩個不同的值......等等,它只是在編輯上,所以什麼是導致數據庫中的值更改時出現問題。可能會成爲某事..... – Tony