banner
biuaxia

biuaxia

"万物皆有裂痕,那是光进来的地方。"
github
bilibili
tg_channel

Golang經緯度DMS解決實際問題

title: Golang 經緯度 DMS 解決實際問題
date: 2022-05-30 10:53:00
toc: false
index_img: https://puep.qpic.cn/coral/Q3auHgzwzM4fgQ41VTF2rGpUMPpyPrsMm6TJcdtuTd00Qp3a7jkPEg/0
category:

  • Go
    tags:
  • 計算
  • 格式

題目#

編寫一個程序,他可以計算出表 火星上的著陸點 中每一對著陸點之間的距離,並回答以下問題:

  • 哪兩個著陸點之間的距離最近?
  • 哪兩個著陸點之間的距離最遠?

之後,請基於表 各行星的測定半徑 定義出新的世界,並執行以下計算。

  • 計算出英國倫敦(北緯 51°31',西經 0°08')至法國巴黎(北緯 48°51',東經 2°21')之間的距離。
  • 計算出你所在的城市與首都之間的距離。
  • 計算出火星上夏普山(南緯 5°4'48",東經 137°51')和奧林帕斯山(北緯 18°39',東經 226°12')之間的距離。

火星上的著陸點#

探測器或著陸器著陸點緯度經度
勇氣號哥倫比亞紀念站南緯 14°34'6.2"東經 175°28'21.5"
機遇號挑戰者紀念站南緯 1°56'46.3"東經 354°28'24.2"
好奇號布萊德柏利著陸地南緯 4°35'22.2"東經 137°26'30.1"
洞察號埃律西昂平原北緯 4°30'0.0"東經 135°54'0"

各行星的測定半徑#

行星半徑 /km行星半徑 /km
水星2439.7木星69911
金星6051.8土星58232
地球6371.0天王星25362
火星3389.5海王星24622

代碼#

package main

import (
	"fmt"
	"math"
	"strings"
)

type location struct {
	lat, long float64
}

func newLocation(lat, long coordinate) location {
	return location{
		lat:  lat.decimal(),
		long: long.decimal(),
	}
}

type coordinate struct {
	d, m, s float64
	h       rune
}

func (c coordinate) decimal() float64 {
	sign := 1.0
	switch strings.ToLower(string(c.h)) {
	case "s", "w":
		sign = -1
	}
	return sign * (c.d + c.m/60 + c.s/3600)
}

type world struct {
	radius float64
}

func (w world) distance(p1, p2 location) float64 {
	s1, c1 := math.Sincos(rad(p1.lat))
	s2, c2 := math.Sincos(rad(p2.lat))
	clong := math.Cos(rad(p1.long - p2.long))
	return w.radius * math.Acos(s1*s2+c1*c2*clong)
}

func rad(deg float64) float64 {
	return deg * math.Pi / 180
}

var (
	mars  = world{radius: 3389.5}
	earth = world{radius: 6371}
)

func main() {
	// 南緯14°34'6.2",東經175°28'21.5"
	spirit := newLocation(coordinate{d: 14, m: 34, s: 6.2, h: 'S'}, coordinate{d: 175, m: 28, s: 21.5, h: 'E'})
	// 南緯1°56'46.3",東經354°28'24.2"
	opportunity := newLocation(coordinate{d: 1, m: 56, s: 46.3, h: 'S'}, coordinate{d: 354, m: 28, s: 24.2, h: 'E'})
	// 南緯4°35'22.2",東經137°26'30.1"
	curiosity := newLocation(coordinate{d: 4, m: 35, s: 22.2, h: 'S'}, coordinate{d: 137, m: 26, s: 30.1, h: 'E'})
	// 北緯4°30'0.0",東經135°54'0"
	insight := newLocation(coordinate{d: 4, m: 30, s: 0.0, h: 'N'}, coordinate{d: 135, m: 54, s: 0, h: 'E'})

	fmt.Printf("Spirit to Opportunity %.2f km\n", mars.distance(spirit, opportunity))
	fmt.Printf("Spirit to Curiosity %.2f km\n", mars.distance(spirit, curiosity))
	fmt.Printf("Spirit to Insight %.2f km\n", mars.distance(spirit, insight))

	fmt.Printf("Opportunity to Curiosity %.2f km\n", mars.distance(opportunity, curiosity))
	fmt.Printf("Opportunity to Insight %.2f km\n", mars.distance(opportunity, insight))

	fmt.Printf("Curiosity to Insight %.2f km\n", mars.distance(curiosity, insight))

	london := newLocation(coordinate{d: 51, m: 30, s: 0, h: 'N'}, coordinate{d: 0, m: 8, s: 0, h: 'W'})
	paris := newLocation(coordinate{d: 48, m: 51, s: 0, h: 'N'}, coordinate{d: 2, m: 21, s: 0, h: 'E'})
	fmt.Printf("Lindon to Paris %.2f km\n", earth.distance(london, paris))

	// Ref: https://map.jiqrxx.com/jingweidu/
	chengdu := newLocation(coordinate{d: 30, m: 39, s: 3.24, h: 'N'}, coordinate{d: 104, m: 04, s: 35.16, h: 'E'})
	home := newLocation(coordinate{d: 30, m: 32, s: 51.02, h: 'N'}, coordinate{d: 104, m: 06, s: 15.70, h: 'E'})
	fmt.Printf("Chengdu to Home %.2f km\n", earth.distance(chengdu, home))

	mountSharp := newLocation(coordinate{5, 4, 48, 'S'}, coordinate{137, 51, 0, 'E'})
	olympusMons := newLocation(coordinate{18, 39, 0, 'N'}, coordinate{226, 12, 0, 'E'})
	fmt.Printf("Mount Sharp to Olympus Mons %.2f km\n", mars.distance(mountSharp, olympusMons))
}

結果#

Spirit to Opportunity 9669.71 km
Spirit to Curiosity 2291.55 km
Spirit to Insight 2580.13 km
Opportunity to Curiosity 8425.63 km
Opportunity to Insight 8365.45 km
Curiosity to Insight 545.38 km
Lindon to Paris 343.62 km
Chengdu to Home 11.80 km
Mount Sharp to Olympus Mons 5328.08 km

總結#

  • Go 語言透過組合結構和方法,在沒有引入任何新特性的情況下在很大程度上實現了傳統語言的面向對象特性。
  • Go 語言沒有為構造函數提供特殊的語言特性,構造函數和其他函數一樣只是普通的函數。
  • Go 語言選擇了名稱格式為 newType 或者 NewType 的函數用於構造指定類型的值,至於首字母的大小寫則有函數是否需要導出以供其它包使用來決定。
  • DMS 格式(degrees/minutes/seconds,度 / 分 / 秒)分和秒表示的是位置而不是時間,其中每 60 秒(")為一分,每 60 分(')為一度。例如,布萊德柏利著陸點的位置用 DMS 格式表示就是 南緯 4°35'22.2",東經 137°26'30.1"
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。