在Python中如何将DD(十进制度数)转换为DMS(度分秒)?

24

如何在Python中将十进制度数转换为度分秒?是否已经有现成的公式可用?


@David:这只是将小数部分乘以60的问题。您还需要什么? - SilentGhost
15个回答

28

这正是 divmod 的用途所在:

def decdeg2dms(dd):
    mult = -1 if dd < 0 else 1
    mnt,sec = divmod(abs(dd)*3600, 60)
    deg,mnt = divmod(mnt, 60)
    return mult*deg, mult*mnt, mult*sec

dd = 45 + 30/60 + 1/3600
print(decdeg2dms(dd))

# negative value returns all negative elements
print(decdeg2dms(-122.442))

输出:

(45.0, 30.0, 1.0)
(-122.0, -26.0, -31.199999999953434)

2
它不能处理负数。-122.442 返回 (-123,33,28.8)。应该是 (-122,26,31.12)。 - Erik L
@baens - 你是指 (-122, -26, -31.12) 吗?我认为 -123 + 33/60 + 28.8/3600 实际上等于 -122.442 - PaulMcG
将3600乘以一个数,然后除以60两次,看起来不够高效。 - musiphil
正如 @erik-l 所说,它对于负角度给出错误的结果,必须进行更正。 - John Smith
2
只用了10年,但现在有一个解决方案,其中所有值都是正数或负数,而不是混合的。 - PaulMcG

17

这是我基于Paul McGuire的更新版本。这个版本应该正确处理负数。

def decdeg2dms(dd):
   is_positive = dd >= 0
   dd = abs(dd)
   minutes,seconds = divmod(dd*3600,60)
   degrees,minutes = divmod(minutes,60)
   degrees = degrees if is_positive else -degrees
   return (degrees,minutes,seconds)

如果 is_positive 为 False,则还需要对 minutesseconds 取反。 - PaulMcG

14
如果您想正确处理负数,那么第一个非零度量被设置为负数。将度、分和秒全部指定为负数是违反常规的做法(维基百科展示了40° 26.7717、-79° 56.93172作为度-分表示法的有效示例,其中度数为负数且分钟没有符号),而如果度数部分为0,则将度数设置为负数没有任何效果。以下是一种函数,可以足够地处理这个问题,基于Paul McGuire和baens的函数:
def decdeg2dms(dd):
    negative = dd < 0
    dd = abs(dd)
    minutes,seconds = divmod(dd*3600,60)
    degrees,minutes = divmod(minutes,60)
    if negative:
        if degrees > 0:
            degrees = -degrees
        elif minutes > 0:
            minutes = -minutes
        else:
            seconds = -seconds
    return (degrees,minutes,seconds)

8

只需要进行几个* 60的乘法和几次int的截断,即可实现:

>>> decdegrees = 31.125
>>> degrees = int(decdegrees)
>>> temp = 60 * (decdegrees - degrees)
>>> minutes = int(temp)
>>> seconds = 60 * (temp - minutes)
>>> print degrees, minutes, seconds
31 7 30.0
>>> 

5

这是我的Python代码:

def DecimaltoDMS(Decimal):
    d = int(Decimal)
    m = int((Decimal - d) * 60)
    s = (Decimal - d - m/60) * 3600.00
    z= round(s, 2)
    if d >= 0:
        print ("N ", abs(d), "º ", abs(m), "' ", abs(z), '" ')
    else:
        print ("S ", abs(d), "º ", abs(m), "' ", abs(z), '" ')

4
Decimal用作变量名称可能会与decimal.Decimal冲突,并不是一个好主意。 - musiphil

5
提高 @chqrlie 的答案:
    def deg_to_dms(deg, type='lat'):
        decimals, number = math.modf(deg)
        d = int(number)
        m = int(decimals * 60)
        s = (deg - d - m / 60) * 3600.00
        compass = {
            'lat': ('N','S'),
            'lon': ('E','W')
        }
        compass_str = compass[type][0 if d >= 0 else 1]
        return '{}º{}\'{:.2f}"{}'.format(abs(d), abs(m), abs(s), compass_str)

4

这是我略微不同的方法,对于正负十进制度数在我的惠普Prime上与原方法相同...

def dms(deg):
    f,d = math.modf(deg)
    s,m = math.modf(abs(f) * 60)
    return (d,m,s * 60)

3

最好将该符号分开返回,这样就可以用于选择('N', 'S')('E', 'W')等。

import math

def dd_to_dms(degs):
    neg = degs < 0
    degs = (-1) ** neg * degs
    degs, d_int = math.modf(degs)
    mins, m_int = math.modf(60 * degs)
    secs        =           60 * mins
    return neg, d_int, m_int, secs

0

现在我们可以使用LatLon库了...

https://pypi.org/project/LatLon/

>> palmyra = LatLon(Latitude(5.8833), Longitude(-162.0833)) # Location of Palmyra Atoll in decimal degrees
>> palmyra = LatLon(5.8833, -162.0833) # Same thing but simpler! 
>> palmyra = LatLon(Latitude(degree = 5, minute = 52, second = 59.88),
                     Longitude(degree = -162, minute = -4.998) # or more complicated!
>> print palmyra.to_string('d% %m% %S% %H') # Print coordinates to degree minute second
('5 52 59.88 N', '162 4 59.88 W')`

你提供的版本仅经过Python 2.7测试。虽然有一个更新的版本,但它也只经过Python 3.6测试。https://pypi.org/project/latlon3 - user3185563
1
嗨,我现在在我的Python 3.7.4中使用的是LatLon23。 https://pypi.org/project/LatLon23/#description - Sungsoo Lim
太好了。它似乎在3.9上也能正常工作。它比Geographiclib更直接,而我最终选择了后者。 - user3185563
对于遵循文档的用户,文档中说您可以使用语法 import latlon 导入模块。请注意,您需要使用以下语法 from latlon import LatLon 才能使这些示例正常工作。请注意大小写。 - user6743474

0
使用 fmod 和四舍五入来分离度数和小数部分。将小数部分乘以60并重复操作,得到分钟和余数。然后再将最后一部分乘以60,得到秒数。

1
您可能指的是 math.modf - musiphil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接