返回float的Python方法返回相同原始数据的不同值

时间:2014-02-14 16:14:27

标签: python django floating-point

另一个Python浮点问题。我正在创建一个应用程序来帮助我们的培训部门。该应用程序的一部分是处理类评估。评估包括一类设备,书面测试分数,操作测试分数和操作测试时间。这很有希望。

有一个计算得分的公式:

score = written_test + operational - best_decimal_time + decimal_time
percentage = score / best score

现在,界面允许用户输入测试分数以及道路测试的分钟和秒数。从理论上讲,最佳时间的分数是:

written_test + operational

因为小数时间会偏移。

请注意,written_teststudent

Evaluation属性的属性

使用Django评估的模型定义是:

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

当我删除记录并使用minute = 3和seconds = 2重新开始时,我得到:

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()结果,但界面中显示的内容不同。

建议?

1 个答案:

答案 0 :(得分:0)

好吧,我陷入了浮动的境地,我错过了实际的问题。问题是我需要检查数据库中的最佳时间是否属于当前评估,如果是,则使用self而不是数据库值。

+1让Messa让我思考。