Sqlalchemy:纬度和经度浮点精度?
我正在使用 Sqlalchemy 来定义我的表等,这是我想出的一些代码:
locations = Table('locations', Base.metadata,
Column("lat", Float(Precision=64), primary_key=True),
Column("lng", Float(Precision=64), primary_key=True),
)
我读了 某处纬度和经度需要比浮点数,通常是双精度。所以我手动将精度设置为64,这足够了吗?矫枉过正?这对我的情况有帮助吗?
I'm using Sqlalchemy to define my tables and such and here is some code I came up with:
locations = Table('locations', Base.metadata,
Column("lat", Float(Precision=64), primary_key=True),
Column("lng", Float(Precision=64), primary_key=True),
)
I read somewhere that latitude and longitude require better precision than floats, usually double precision. So I set the precision manually to 64, is this sufficient? Overkill? Would this even help for my situation?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这里没有其他人提供具体的数字来证明浮点纬度/经度在最坏情况下的准确性。我需要了解我正在做的事情,所以这是我的分析,以防对其他人有所帮助。
单精度浮点在有效数(数字的二进制指数表示法)中提供 24 位精度。随着数字的整个部分变大,小数点后的位数会减少。因此,纬度或经度的最坏情况精度是当幅度尽可能远离 0 时。假设您将纬度限制为 [-90, 90],经度限制为 (-180, 180],最坏的情况将是位于赤道的经度 180。
在二进制中,180 需要可用的 24 位中的 8 位,小数点后保留 16 位,因此,在该经度处连续可表示的值之间的距离将为 2^-16 度。 (大约 1.526E-5)将该数字(以弧度为单位)乘以地球在赤道处的 WGS-84 半径 (6,378,137 m),得出最坏情况下的精度:
对以弧度存储的纬度/经度进行相同的分析 。最后
,如果将纬度标准化为范围 [-1, 1],将经度标准化为范围 (-1, 1],那么您可以实现以下最坏情况的精度:
因此,以弧度存储纬度/经度可为您带来大约 7 英寸的额外精度,而以标准化形式存储它们将为您带来大约 1'8" 的额外精度,无论是在最坏的情况。
如果在双精度和单精度之间转换时进行舍入(而不是截断),则单精度值将在上面计算的两个连续值之间的距离的一半以内。
Nobody else here provided concrete numbers with proof for the worst-case accuracy of a floating point lat/long. I needed to know this for something I was working on, so here is my analysis in case it helps someone else.
A single-precision floating point offers 24-bits of precision in the significand (the binary exponential notation of a number). As the whole part of the number gets larger, the number of bits after the decimal goes down. Therefore, the worst-case accuracy for a latitude or longitude is when the magnitude is as far away from 0 as is possible. Assuming you bound your latitudes to [-90, 90] and longitudes from (-180, 180], the worst-case will be at the equator for longitude 180.
In binary, 180 requires 8-bits of the 24-bits available, leaving 16 bits after the decimal point. Therefore, the distance between consecutively representable values at this longitude would be 2^-16 deg (approximately 1.526E-5). Multiplying that number (in radians) by the WGS-84 radius of the Earth at the equator (6,378,137 m) yields a worst-case precision of:
The same analysis against lat/longs stored in radians yields the following:
And finally, if you normalize the latitudes to the range [-1, 1] and the longitudes to the range (-1, 1], then you can achieve the following worst-case precision:
So storing lat/long in radians buys you around 7 inches of additional accuracy, and storing them in normalized form buys you around 1'8" of additional accuracy, both in the worst-case scenario.
If, when converting between double-precision and single-precision you rounded (instead of truncating), the single-precision value will be within half of the distance between two consecutive values computed above.
这取决于您使用数据的目的。如果您使用浮标,只要您只需要大约米级的细节就可以了。如果用户放大得太远,在图形应用程序中使用数据将导致抖动效果。有关抖动的更多信息,请参阅精度,精度。希望这有帮助。
It depends on what you are using your data for. If you use a float it will be ok if the you only need it down to about the meter level of detail. Using the data in graphically applications will cause a jitter effect if the user zooms in to far. For more about jitter and see Precisions, Precisions. Hope this helps.
更新:杰夫的回答有更好的分析。但是...
为了改进 Jeff 的答案:
如果将实际角度(以弧度为单位)除以 π,从而以从 0 到 ±1 的范围对角度进行编码,那么应该可以使用有效数的所有数字(23位(24 - 1 个符号位))。精度将是:
我的旧答案:
32 位浮点数可以表示精度约为 7.2 位小数的数字。这是一个近似值,因为浮点数实际上是二进制的,当转换为十进制时,有效位数可能会有所不同。
如果我们将其视为 6 个十进制数字的精度(为了安全起见),并且如果我们以度为单位存储纬度和经度,那么我们得到的精度约为 1/1000 度,即精度约为 111最坏情况下的米。在最好的情况下,如果我们得到小数点后 7 位的精度,则精度约为 11.1 米。
使用弧度作为单位可以获得更好的精度。在最坏的情况下,我们得到的精度为百万分之一弧度,约为 63 米。最好的情况是百万分之一弧度,即大约 6 米。
不用说,64 位浮点数将非常精确(最坏情况下约为 6 微米)。
Update: Jeff's answer has a better analysis. However...
To improve upon Jeff's answer:
If you divide the actual angle in radians by π, thus encoding the angle in a scale going from 0 to ±1, then it should be possible to use all the digits of the significand (23 bits (24 - 1 sign bit)). The precision would then be:
My Old answer:
A 32 bit floating point number can represent a number with about 7.2 decimal digits of precision. This is an approximation because the floating point number is actually in binary, and when converted to decimal, the number of significant digits might vary.
If we take it as 6 decimal digits of precision (to play on the safe side), and if we are storing latitude and longitude in degrees, then we get a precision of about 1/1000th of a degree which is a precision of about 111 meters in the worst case. In the best case, if we get 7 decimal digits of precision, the accuracy would be about 11.1 meters.
It is possible to get a better precision using radians as the unit. In the worst case we get a precision of 10 millionth of a radian which is about 63 meters. In the best case, it would be 1 millionth of a radian which is about 6 meters.
Needless to say, a 64bit floating point number would be extremely precise (about 6 micro meters in the worst case).
TL;DR:如果一米分辨率可以接受,那么单精度浮点存储度数也是可以接受的。
这个答案有点晚了,但我自己需要一个可靠的答案,因此编写了一些代码来快速获得它。当然还有更优雅的方法可以做到这一点,但它看起来很有效。正如 Jeff 所指出的,最坏的情况将发生在 +/- 180 度经度(即日期变更线)处。
根据下面的代码,使用单精度浮点数存储度数,单精度浮点数在日期变更线处的精确度为 0.85 米。当接近本初子午线时,精度显着提高(以毫米为单位)。
这段代码的输出是
TL;DR: if one-meter resolution is acceptable then a single-precision float storing degrees is acceptable.
This answer is a bit late to the party but I needed a solid answer myself and so hacked out some code to quickly get it. There are of course more elegant ways to do this, but it looks to work. As noted by Jeff, the worst case scenario will be at +/- 180 degrees longitude (ie, the date line).
Per the code below, a single-precision float is accurate to 0.85 meters at the date line using single-precision floats storing degrees. Accuracy increases significantly (to w/in mm) when close to the Prime meridian.
Output from this code is