python – django float或decimal在保存时无意中舍入

我想在Place模型中保存纬度和经度.

我尝试了两个字段,floatfield和decimalfield.

1. FloatField模型

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

2. DecimalField模型

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个数字(不是“十六个小数位”)之后,保存时会无意中舍入.

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文件中找不到关于这个“无意的回合”的任何解释.请帮忙.谢谢.

最佳答案 你不能在django docs中找到’无意的舍入’,因为django不是这里的罪魁祸首.

它的MYSQL在您的列数据类型为Float时进行舍入.

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而且数字仍在四舍五入.这可能会发生,因为您的表列仍然是Float类型而不是Decimal.

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

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

如果您使用的是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;有关您遇到的问题的信息,请参阅here.

点赞