130

What is the best data type to use when storing geopositional data in C#? I would use decimal for its exactness, but operations on decimal floating point numbers are slower then binary floating point numbers (double).

I read that most of the time you won't need any more than 6 or 7 digits of precision for latitude or longitude. Does the inexactness of doubles even matter then or can it be ignored?

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
KRTac
  • 2,767
  • 4
  • 22
  • 18
  • 7
    I'd ask the opposite question: Does the performance difference even matter or can it be ignored? – Heinzi Jan 21 '15 at 13:13
  • 1
    Decimal for absolute precision. If you are storing millions on them, you can save a bit on size and improve a bit on performance using double, but negligible. – Murray Foxcroft Jan 21 '15 at 13:15
  • 2
    In database you should use "sql spatial data type" to store longitude and latitude – azhar_SE_nextbridge Jan 21 '15 at 13:16
  • 9
    Note that the .NET BCL itself uses doubles in its [GeoCoordinate class](https://msdn.microsoft.com/en-us/library/system.device.location.geocoordinate(v=vs.100).aspx), which is a strong indication that the precision might be sufficient. – Heinzi Jan 21 '15 at 13:17
  • 2
    NodaTime's TzdbZoneLocation uses double as well. – Rick Davin Jan 21 '15 at 13:19
  • 2
    double vs decimal = 32bits vs 128bits = 4 bytes vs 16 bytes – Franck Jan 21 '15 at 13:27
  • 5
    1) I'd consider fixed-point. 2) Since you often need to do trigonometric operations on geo coordinates, and those are only implemented for `double`, `double` might be the best fit. – CodesInChaos Jan 21 '15 at 13:41
  • 2
    @Franck Small correction...double is a 64-bit number. https://msdn.microsoft.com/en-us/library/system.double.aspx#Remarks – MattM Nov 08 '16 at 21:02

5 Answers5

165

Go for double, there are several reasons.

  • Trigonometric functions are available only for double
  • Precision of double (range of 100 nanometers) is far beyond anything you'll ever require for Lat/Lon values
  • GeoCoordinate Class and third-Party modules (e.g. DotSpatial) also use double for coordinates
Wernfried Domscheit
  • 54,457
  • 9
  • 76
  • 110
103

A double has up to 15 decimal digits of precision. So, lets assume three of those digits are going to be on the left of the decimal point for lat/long values (max of 180deg). This leaves 12 digits of precision on the right. Since a degree of lat/long is ~111km, 5 of those 12 digits would give us precision to the meter. 3 more digits would give us precision to the millimeter. The remaining 4 digits would get us precision to around 100 nanometers. Since double will win from the perspective of performance and memory, I see no reason to even consider using decimal.

MarkPflug
  • 28,292
  • 8
  • 46
  • 54
7

I faced this question quite a while ago when i started with spacial programming. I read a book a while ago that led me to this.

//sql server has a really cool dll that deals with spacial data such like
//geography points and so on. 
//add this namespace
Using Microsoft.SqlServer.Types;

//SqlGeography.Point(dblLat, dblLon, srid)

var lat_lon_point = Microsoft.SqlServer.Types.SqlGeography.Point(lat, lon, 4326);

This is the best way when working in your application with spacial data. then to save the data use this in sql

CREATE TABLE myGeoTable
{
LatLonPoint GEOMETRY 
}

else, if you are using something else that isnt sql just convert the point to hexadecimal and store it. I know after a long time using spacial that this is the safest.

Jonny
  • 401
  • 2
  • 11
  • 1
    I am having trouble finding LatLonPoint, what references or packages did you have to include or what 'usings' in your c# project? (assuming the create table was for Identity model / c# code, because that type doesn't evaluate in SSMS either). thank you in advance! – Chris May 23 '19 at 13:28
4

Double

Combining the answers, it is how Microsoft represents it itself in SqlGeography library

[get: Microsoft.SqlServer.Server.SqlMethod(IsDeterministic=true, IsPrecise=true)]
public System.Data.SqlTypes.SqlDouble Lat { get; }

Property Value

SqlDouble

A SqlDouble value that specifies the latitude.

2

If you are using .net ef core, I would recommend you the NetTopologySuite library. Read the full documentation at below link: https://learn.microsoft.com/en-us/ef/core/modeling/spatial

Abuzar G
  • 103
  • 1
  • 4