django float 或 decimal 在保存时无意中四舍五入

django float or decimal are rounded unintentionally when saving

我想在 Place 模型中保存经纬度。 我尝试了两个字段,floatfield 和 decimalfield。

1。浮动字段模型

class Place1(models.Model):
    latitude = models.FloatField()
    longitude = models.FloatField()

2。十进制字段模型

class Place2(models.Model):
    latitude = models.DecimalField(max_digits=18, decimal_places=16)
    longitude = models.DecimalField(max_digits=19, decimal_places=16)

两个字段都适用于以下值。

10.1
10.12
10.123
10.1234
...
10.1234567890123

但是,在第 16 个数字(不是 'sixteen decimal places')之后,保存时无意中四舍五入

place1 = Place1.objects.create(
            latitude=10.123456789012345,
            longitude=100.123456789012345
         )

>>place1.latitude
10.123456789012345 # works well

>>place1.longitude
100.123456789012345 # works well

# Unintentionally rounded when I get object from db. 
>>Place.objects.last().latitude
10.12345678901235 # unintentionally rounded

>>Place.objects.last().longitude
100.1234567890123 # unintentionally rounded



place2 = Place2.objects.create(
        latitude=Decimal('10.123456789012345'),
        longitude=Decimal('100.123456789012345')
     )

>>place2.latitude
Decimal('10.1234567890123450') # works well

>>place2.longitude
Decimal('100.1234567890123450') # works well

# Unintentionally rounded when I get object from db. 
>>Place.objects.last().latitude
Decimal('10.1234567890123500') # unintentionally rounded

>>Place.objects.last().longitude
Decimal('100.1234567890123000') # unintentionally rounded

我在 django 文档中找不到关于此 'unintentional round' 的任何解释。请帮忙。谢谢

你在 django 文档中找不到 'unintentional rounding' 因为 django 不是这里的罪魁祸首。

当您的列数据类型为 Float 时,MYSQL 会进行舍入。

For maximum portability, code requiring storage of approximate numeric data values should use FLOAT or DOUBLE PRECISION with no specification of precision or number of digits.

Because floating-point values are approximate and not stored as exact values, attempts to treat them as exact in comparisons may lead to problems. They are also subject to platform or implementation dependencies.

但为了值的准确性,您应该使用 DecimalField.

您说您使用了 DecimalField 并且数字仍在四舍五入。这可能是因为您的 table 列 类型仍然是 Float 而不是 Decimal

将您的 table 列类型更改为十进制,您可以看到更改。

示例 SQL 语法 ALTER TABLE your_table MODIFY latitude decimal(m,n);,或

如果您正在使用 MYSQL Workbench 或任何 UI 界面,请直接从列信息选项卡(他们有一个)更改它

The DECIMAL and NUMERIC types store exact numeric data values. These types are used when it is important to preserve exact precision

In a DECIMAL column declaration, the precision and scale can be (and usually is) specified; for example: latitude DECIMAL(m,n)

The precision (m) represents the number of significant digits that are stored for values, and the scale (n) represents the number of digits that can be stored following the decimal point .

在这里为您的字段纬度和经度选择您想要的精度比例

有关您遇到的问题的信息,请参阅 here for more info on Decimal data type and here