Bittiğinde doğru boylamın hesaplanması | 180 |?


11

Lat-lng değerlerini düzeltmek için bir "formül" geliştirmeye çalışıyorum.

Ben vue-broşür kullanıyorum ama "ilk" dünyanın dışına kaydırdığınızda büyük sayılar elde edersiniz. +180 üstü veya -180 altı.

Örneğin: Amerika'ya sağa (doğu yönü) kaydırdığımda lng 215 olarak alıyorum. Aklımda, sadece 215-360=-145

Aynı şey doğu rusya'yı sola (batı yönü) kaydırdığımda ve örneğin -222 elde ettiğim için de geçerli. Şimdi hesaplamam gerekiyor-222+360=138

Ancak, dünya belirsiz olduğu için kullanıcı 8. dünyaya kayabilir ve değerleri ayarlamak zorunda kaldım.

Doğru boylamı hesaplamak mümkün mü? (ve başka bir gereksinim kullanıcı ilk dünyada olduğunda, 24 lng hala 24 lng olmalıdır.

Yanıtlar:


16

-180 - 180 aralığında olana kadar değerinize tekrar tekrar 360 eklemeniz (veya çıkarmanız) gerekir. Bu nedenle genellikle aşağıdaki gibi bir çift döngü:

lon = -187;
while(lon < -180){
  lon +=360;
}
while (lon > 180){
  lon -= 360;
}

yanlış yol işaretleri? İlk durumda lon + = 360 olmalıdır.
JimT

4
Eğer while (Math.abs(lon) > 180) { lon -= Math.sign(lon) * 360 }benim sürümüm muhtemelen herhangi bir fark yaratmaz bir optimizasyon iken, senin versiyonu aslında açıklama ile eşleşir çünkü ben bir cevap olarak vermiyorum tek bir döngü ile yapabilirsiniz. Bunu, bazı şeylerin diğerlerinden daha optimize edilmiş, birden çok şekilde yapılabileceğini hatırlatmak için bir yorum olarak saklıyorum.
Andrei

2
Ben döngü başına 2 işlev çağrıları kullanır ve benim döngülerden sadece hiç yürütmek gibi hiç birini kullanmak sanmıyorum. Muhtemelen bu örnekte bir fark
Ian Turton

fonksiyonlara benzemelerine rağmen, JavaScript'teki Matematik fonksiyonları daha ayrıntılı sembollere sahip operatörler gibi görülmelidir. Bu anlamda + - ve hatta <işlevleri de görebiliriz. Edit: Ben aslında işe yaramadı bir çözüm vardı
Andrei

2
Yapamaz lon %= 180mısın?
Monica'nın Davası

15

Koşulları ve işlev çağrılarını önleyen bir cevap:

longitude = (longitude % 360 + 540) % 360 - 180

Https://jsperf.com/longitude-normalisation adresinde hızlı bir mikrobenchmark yazdım ve koşullu kod, giriş değerlerinin 'makul' aralıkları için daha hızlı görünüyor (makinemdeki Chrome'da). Genel olarak, muhtemelen bu gibi küçük hesaplamalarda performans konusunda endişelenmemelisiniz, kod tabanınızın geri kalanıyla okunabilirlik ve tutarlılığa daha fazla ağırlık verin.

Bu durumda muhtemelen daha da önemli olan, kodunuzun aşırı giriş değerleriyle (1e10, Infinity vb.) Karşılaşıp karşılaşamayacağı sorusudur. Öyleyse, döngü uygulaması , programınızı gerçekten yavaş veya sessiz bir şekilde askıya alabilir. Bu, kutupların yakınında yapılan hesaplamalar ile meydana gelebilir, örneğin bir direkten belirli bir mesafeye (açı yerine) doğu veya batı kaydırmaya çalışmak kolayca sonsuz bir boylam ile sonuçlanabilir.


1
İlginç. Bir FP bölünmesine karşı koşullu bir yarış yapalım. Hmmm merak ediyorum.
Joshua

1
@Joshua Koşullu bir atlama kullanamazsınız. Bir döngü olarak adlandırılan birden çok koşullu atlama kullanmanız gerekir . (Artı döngü, kayan nokta ek içerir, bu serbest değildir.) Döngünün kaç yineleme ihtiyacı girdiye bağlıdır. Performansa bakmak için veriler hakkında bir şeyler bilmek zorundasınız. Büyük çoğunluk istenen aralığa yakınsa ve çok az yineleme gerektiriyorsa, ekleme döngüsü daha hızlı olabilir, ancak alayınızın önerdiği kadar açık değildir.
jpmc26

1
@ jpmc26: Bu durumda, döngüde birden çok kez dolaşmayı beklemek saçmadır.
Joshua

1
Alaycılık yoktu. Aslında hangi yöne düşeceğini bilmiyorum.
Joshua

1
@Joshua evet, ben de emin değildim :). Performans cevabına daha fazla şey ekledim (ve döngü kodunun olası bir arıza durumu)
Joe Lee-Moyet

5

Tek astarı:

normalized = remainder(longitude, 360);

Açıklama: Tam dönüşleri (360 °) göz ardı ettikten sonra nelerin kaldığını bilmek istersiniz.

Bu sürece normalleştirme denir.

Örnek (cpp.sh)


1
Bu Shadrix'in istediği gibi [-180, 180] ile değil, [0, 360) değeriyle sonuçlanmaz mı?
Şapkalı Adam

Bu örneği kontrol @TheGuywithTheHat: cpp.sh/7uy2v
Tabanlı

Ah, bunun C ++ olduğunu bilmiyordum. Shadrix'in JavaScript bağlamında, remainderolarak yorumladım modulus. JS'deki modül [0, 360) ile sonuçlanacaktır.
Şapkalı Adam

1
Bunun işe yarayacağını sanmıyorum. 360 iff sonucunu> 180 çıkarmanız gerekir. JavaScript ile yeni fark ettiğim bir diğer problem, modulo'nun 0'da simetrik olmasıdır, örneğin -1 % 3burada çalışması için gerekli olduğu gibi -1 değil 2'dir. remainderharika bir C ++ çözümüdür, ancak maalesef JS'de kullanışlı olacak kadar benzer bir işlev / operatör yoktur.
Şapkalı Adam

0

Başka bir seçenek: boylam = atan2 (cos (uzun), günah (uzun))


1
Bu iyi bir fikir gibi görünmüyor. Anlamak çok zor, hesaplama açısından pahalı ve potansiyel olarak yuvarlama hatalarına maruz.
David Richerby

0

Kullandığınız programlama dili kayan nokta numaralarında (Python ve Ruby gibi)% (mod) operatörünü destekliyorsa, bunu kullanmanızı öneririm. Aksi takdirde, diğer bazı diller (C ve C ++ gibi) fmod () kullanmanıza izin verir.

(Hangi mod operatörünü kullanırsanız kullanın, kayan noktalı sayılarda mod işlemleri yapacağından ve size her zaman olumsuz olmayan cevaplar vereceğinden emin olun. Aksi takdirde, birçoğunuz enlem / boylam noktaları doğru değil.)

Şöyle kullanın:

# Put the longitude in the range of [0,360):
longitude %= 360

# Put the longitude in the range of [-180,180):
if longitude >= 180:
    longitude -= 360

Hepsini tek bir satırda yapmayı tercih ediyorsanız:

# Put the longitude in the range of [-180,180):
longitude = (longitude + 180) % 360 - 180

Bu yaklaşımların döngüleri yoktur, bu nedenle gözleminiz dünyanın etrafında kaç kez dönmüş olursa olsun, boylam değerlerini tekrar tekrar eklemeye veya çıkarmaya gerek kalmadan normalleştirirler.

Düzenle:

Hmmm ... Javascript'in %düşündüğüm gibi negatif değerlerle başa çıkmadığını fark ettim .

Bu durumda, bu tek astarı deneyin:

longitude = (longitude + 36180) % 360 - 180

36180De, eklediğimiz 36.000 + 180. 36.000 pozitif etki alanına negatif bir değer taşımaktır olduğunu ve 180'den fazla yüzden modded zaman bu kadar kaydırmaya olduğu 360aralığında, bu olacak [0360) . - 180Parça değişimleri bu [-180,180) aralığında geri.

İşte 36.000'in yeterince büyük olmasına dayanmayan başka bir tek astar:

longitude = (longitude % 360 + 360 + 180) % 360 - 180

longitude % 360 + 360Daha sonra modded ne zaman parçası pozitif etki alanındaki değeri kalır sağlayacaktır 360. + 180Bu daha sonra (ile çıkarılır 180 alır parça değişimleri bu fazla böylece - 180), bu [-180,180) arasında arzu edilen aralık içinde olacak.


1
Not: C, C ++ fmod(longitude, 360)-> (-360.0 ... +360.0) ve ilongitude % 360-> [-359 ... +359].
chux - Monica'yı eski haline getir

@chux - Bunu bilmiyordum, bu yüzden test ettim ve haklısın. Bunu işaret ettiğiniz için teşekkür ederim.
JL
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.