django浮点数或十进制数在保存时无意舍入

jey*_*gOh 5 python django floating-point decimal latitude-longitude

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

1. FloatField模型

class Place1(models.Model):
    latitude = models.FloatField()
    longitude = models.FloatField()
Run Code Online (Sandbox Code Playgroud)

2. DecimalField模型

class Place2(models.Model):
    latitude = models.DecimalField(max_digits=18, decimal_places=16)
    longitude = models.DecimalField(max_digits=19, decimal_places=16)
Run Code Online (Sandbox Code Playgroud)

这两个字段在以下值上均能正常工作。

10.1
10.12
10.123
10.1234
...
10.1234567890123

但是,在第16个数字(不是“ 16个小数位”)之后,在保存时会无意舍入

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
Run Code Online (Sandbox Code Playgroud)

我在Django文档中找不到关于此“意外回合”的任何解释。请帮忙。谢谢。

kap*_*sdv 4

您无法在 django 文档中找到“无意舍入”,因为 django 不是这里的罪魁祸首。

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

为了获得最大的可移植性,需要存储近似数值数据值的代码应使用FLOATDOUBLE PRECISION,而不指定精度或位数。

由于浮点值是近似值并且不存储为精确值,因此尝试在比较中将它们视为精确值可能会导致问题。它们还受到平台或实现依赖性的影响。

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

您说您已经使用了DecimalField并且数字仍在四舍五入。发生这种情况可能是因为您的表列仍然是Float类型而不是Decimal 类型

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

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

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

DECIMAL 和 NUMERIC 类型存储精确的数字数据值。当需要保持精确度时使用这些类型

在 DECIMAL 列声明中,可以(并且通常)指定精度和小数位数;例如:纬度 DECIMAL(m,n)

精度(m) 表示值存储的有效位数,小数位(n)表示小数点后可存储的位数。

在这里帮助您获得您想要的田地纬度和经度的精确刻度

有关 Decimal 数据类型的详细信息,请参阅此处,有关您遇到的问题的信息,请参阅此处。