将用户输入限制为小数点后两位时,处理浮点问题的最佳方法是什么?

问题描述 投票:0回答:1

我目前正在创建一个应用程序,允许用户输入重量并选择他们喜欢的单位(公斤和磅之间)。截至目前,数据库是用 Django 编写的,并将特定日期的每个用户体重条目存储为具有 2 位小数精度的字符串,例如,

weight_kg = models.DecimalField(max_digits=5, decimal_places=2, validators=[MinValueValidator(1)])

我面临的问题是在单位之间更改时丢失数据。例如,如果用户选择 165,以

lbs
为单位,我会将其存储在我的数据库中为
74.84
。当关闭并重新打开页面时,它将获取数据并尝试恢复它。这样做,它会将
74.84kg
更改为
164.99lbs
。数据丢失,因为我们不知道用户是否选择了
164.99lbs
还是舍入错误。

我开始认为我选择将权重存储为字符串是一个错误,但是,使用数字时也会出现同样的问题。比如,

let kg_to_lbs = 2.20462;
let lbs_to_kg = 0.453592;
((165 * lbs_to_kg) * kg_to_lbs) // 164.99....

他们有防止此类问题的最佳实践吗?

其他信息,

  1. 使用旋转按钮将用户输入限制为 2 位小数,即 0 到 1000。
  2. 数据库将权重存储在
    kg
    中,客户端负责将其转换回用于显示的单位并转换为
    kg
    ,然后发送到服务器存储。
javascript floating-point precision
1个回答
-1
投票

您面临的问题是浮点运算中的常见问题,由于计算机存储和处理数字的方式,浮点运算很难准确处理。出现这个问题是因为公斤和磅之间的转换涉及到非整数比率,无法精确表示为浮点数。

处理这个问题的最佳方法是完全避免浮点运算,而是使用定点表示。在这种情况下,您可以将重量存储为整数克(因为 1kg = 1000g),然后在向用户显示该值时转换为千克或磅。

以下是如何在 Django 模型中实现此功能的示例:

蟒蛇

weight_g = models.IntegerField(validators=[MinValueValidator(1)])

def get_weight_kg(self):
    return self.weight_g / 1000

def get_weight_lbs(self):
    return self.weight_g * 0.00220462  

JavaScript

let kg_to_g = 1000;
let lbs_to_g = 453.592;

let user_weight_kg = 165;
let user_weight_lbs = user_weight_kg * kg_to_g / lbs_to_g;

let stored_weight_g = Math.round(user_weight_kg * kg_to_g);
let restored_weight_kg = stored_weight_g / kg_to_g;
let restored_weight_lbs = stored_weight_g / lbs_to_g;

通过使用整数和舍入,可以确保存储和恢复的值尽可能准确,并避免使用浮点数时出现的数据丢失。

© www.soinside.com 2019 - 2024. All rights reserved.