将双类型数据(地理定位)保存到数据库时发生奇怪的(?)值变化

Strange (?) value change when saving double-type data (geolocation) into database

我有两个字段用于存储地理位置数据,在我的 MySQL 数据库中定义为双精度:

`address_geo_latitude` float(10,6) NOT NULL,
`address_geo_longitude` float(10,6) NOT NULL

我正在使用 Yii2 的 double 验证器来验证用户传递的值:

public function rules()
{
    return [
        [['address_geo_latitude', 'address_geo_longitude'], 'double', 'min'=>0, 'max'=>360]
    ];
}

(虽然我的测试似乎证明,这个问题与 Yii2 验证器无关)

在测试期间,我观察到值的奇怪(?)变化,即:

但是:

我错过了什么?我看不到这些背后的任何模式或逻辑。

这是因为我对这种数据的 MySQL 字段声明不正确吗?如果是,那么正确的是什么?几个不同的答案:

建议,如果不使用 MySQL 的 spatial extensions.

,则使用 float(10,6) 是最佳选择

我的测试似乎证明,这个问题与 Yii2 验证器无关,因为值在从数据库重新读取之前一直保持正确:

print_r(Yii::$app->request->post()); //Correct!
print_r($lab->address_geo_latitude); //Correct!

if ($lab->load(Yii::$app->request->post(), 'Lab') && $lab->save()) {
    print_r($lab->address_geo_latitude); //Correct!

    $lab2 = $this->findModel($lab->id);
    print_r($lab2->address_geo_latitude); //<-- HERE! Incorrect!
}

我的问题与this one相反。我的数字 增加 ,不输,准确!并且只针对某些数字,并非总是如此。

这不是因为 Yii,而是因为浮点值在二进制系统中的存储方式。

您可以在 MySQL documentation "Problems with Floating-Point Values" 中阅读:

Floating-point numbers sometimes cause confusion because they are approximate and not stored as exact values. A floating-point value as written in an SQL statement may not be the same as the value represented internally.

Here you can find the great explanation 这个问题有例子。如您所见,数字可能会变大、变小或根本不变,但您始终必须记住,这只是一个近似值。

对于地理定位数据,您可以使用简单的 DECIMAL type to make sure values are stored unchanged in database or use Spacial Data type 优化来存储和查询表示在几何 space 中定义的对象的数据。