LINUX.ORG.RU

Ошибка в переводе десятичных градусов в градусы минуты секунды

 


0

1
(defun rad-to-decimal-deg (alpha-rad)
  (/ (* alpha-rad 180) pi))

(rad-to-decimal-deg 0.0116) => 0.664631042351755
(rad-to-decimal-deg 0.0233) => 1.3349916626548182

(defun decimal-deg-to-dms (n)
  (setq d (round n))
  (setq m (* (- n d) 60))
  (setq s (- (* 3600 (- n d)) (* 60 m)))
  (format "%d° %d' %d''" d m s))

(decimal-deg-to-dms 0.664631042351755) => "1° -20' 0''"
(decimal-deg-to-dms 1.3349916626548182) => "1° 20' 0''"

Где ошибка не вижу.

Проверял вот так


(defun dms-to-rad (d m s)
  (+ (* d (/ pi 180))
     (* m (/ pi (* 180 60)))
     (* s (/ pi (* 180 60 60)))
     ))

            0˚8’0’’
(dms-to-rad 0 8 0) => 0.0023271056693257726
(rad-to-decimal-deg 0.0023271056693257726) => 0.13333333333333333
(decimal-deg-to-dms 0.13333333333333333) => "0° 8' 0''"



Последнее исправление: saufesma (всего исправлений: 1)

В Лиспе операции остатка от деления нету?

(setq d (round n))

Скорее всего это округление к ближайшему целому (0.6 -> 1), а надо с отбрасыванием дробной части (0.6 -> 0).

X512 ★★★★★
()
Ответ на: комментарий от X512
(defun decimal-deg-to-dms (n)
  (setq d (floor n)) -------- переписал
  (setq m (* (- n d) 60))
  (setq s (- (* 3600 (- n d)) (* 60 m)))
  (format "%d° %d' %d''" d m s))

(decimal-deg-to-dms 0.664631042351755) => "0° 39' 0''"
(decimal-deg-to-dms 1.3349916626548182) => "1° 20' 0''"
saufesma
() автор топика

В общем рабочий код на Обероне:

MODULE A;
	IMPORT Log := StdLog, In := i21sysIn;
	
	PROCEDURE DegToDms*;
		VAR n: REAL; nInt: INTEGER; d, m, s: INTEGER;
	BEGIN
		In.Open; ASSERT(In.done);
		In.Real(n); ASSERT(In.done);
		nInt := SHORT(ENTIER(n*3600 + 0.5));
		d := nInt DIV 3600;
		m := nInt DIV 60 MOD 60;
		s := nInt MOD 60;
		Log.Int(d); Log.String("° "); 
		Log.Int(m); Log.String("' "); 
		Log.Int(s); Log.String("''"); Log.Ln;
	END DegToDms;
	
END A.

A.DegToDms 0.664631042351755
0° 39' 53''
A.DegToDms 1.3349916626548182
1° 20' 6''
A.DegToDms 0.13333333333333333
0° 8' 0''

Google подсказывает что операция остатка от деления в Лиспе называется mod.

X512 ★★★★★
()
Ответ на: комментарий от X512

Google подсказывает что операция остатка от деления в Лиспе называется mod.

Да, вот и книжка говорит то же самое

mod dividend divisor [Function]

This function returns the value of dividend modulo divisor; in other words, the remainder after division of dividend by divisor, but with the same sign as divisor.

а вот как переписать код с этой функцией у меня не получается.

saufesma
() автор топика
Последнее исправление: saufesma (всего исправлений: 1)

А я не понимаю, где ты видишь ошибку?

(format «%d° %d' %d"» d m s))

Шаблон %d отсекает дробную часть.

(format "%d" 0.123123123123) -> "0"

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от saufesma

А, я понял. Тебя ноль в секундах смущает. Вот тут ты не отбросил дробную часть.

(setq m (truncate (* (- n d) 60)))

И имей в виду, что %d, как я уже написал, не округлит секунды, а отбросит дробную часть.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
(defun decimal-deg-to-dms (n)
  (setq d (round n))
  (setq m (* (- n d) 60))
  (setq s (- (* 3600 (- n d)) (* 60 m)))
  (format "%d° %d' %d''" d m s))

Зачем эта императивщина? Для кого let* придумали? Ты же уже здесь давно темы про лиспо строчишь, неужели этого еще не усвоил?

OTEU_APUCTOKJ7UU
()
Ответ на: комментарий от OTEU_APUCTOKJ7UU

Ты же уже здесь давно темы про лиспо строчишь, неужели этого еще не усвоил?

Если нет, то что?

saufesma
() автор топика
Ответ на: комментарий от Zubok
(defun decimal-deg-to-dms (n)
  (setq d (floor n))
  (setq m (floor (* (- n d) 60)))
  (setq s (- (* 3600 (- n d)) (* 60 m)))
  (format "%d° %d' %d''" d m s))

только

(decimal-deg-to-dms 0.664631042351755) => 0° 39' 52''
(decimal-deg-to-dms 1.3349916626548182) => 1° 20' 5''
(decimal-deg-to-dms 0.13333333333333333) => 0° 8' 0''


Код на Обероне выдаёт 

A.DegToDms 0.664631042351755
0° 39' 53''
A.DegToDms 1.3349916626548182
1° 20' 6''
A.DegToDms 0.13333333333333333
0° 8' 0''
saufesma
() автор топика
Ответ на: комментарий от Zubok

Включил

(defun decimal-deg-to-dms (n)
  (setq d (round (floor n)))
  (setq m (round (floor (* (- n d) 60))))
  (setq s (round (- (* 3600 (- n d)) (* 60 m))))
  (format "%d° %d' %d''" d m s))

(decimal-deg-to-dms 0.664631042351755) => "0° 39' 53''"
(decimal-deg-to-dms 1.3349916626548182) => 1° 20' 6''"
(decimal-deg-to-dms 0.13333333333333333) => "0° 8' 0''"

С другой стороны ерунда какая-то, я тебя игнорирую и уже давно, а ты опять у меня в треде. А я общаюсь с тобой.

saufesma
() автор топика
Ответ на: комментарий от saufesma

С другой стороны ерунда какая-то, я тебя игнорирую и уже давно, а ты опять у меня в треде. А я общаюсь с тобой.

И правильно! А то оскорблю еще религиозные чувства ненароком. :)

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

А то оскорблю еще религиозные чувства ненароком. :)

Не совсем понял - религиозные чувства, о чём это.

saufesma
() автор топика
Ответ на: комментарий от saufesma

Не совсем понял - религиозные чувства, о чём это.

Ну вот, к примеру. Начинаю оскорблять. :)

(setq d (round (floor n)))
(setq m (round (floor (* (- n d) 60))))
(setq s (round (- (* 3600 (- n d)) (* 60 m))))

(round (floor ())) - это вообще что-то с чем-то. :) Даже если допустить, то попробуй отрицательные углы ввести. Они же допустимы?

(decimal-deg-to-dms 90.664631042351755) -> 90° 39' 53''
(decimal-deg-to-dms -90.664631042351755) -> -91° 20' 7''

Йоу, оскорбил. Говорю же, бери truncate хотя бы (тогда минус будет у всех компонентов DMS). Или знак обрабатывай.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от Zubok

Этот код использую для максимального угла в 4 градуса, другие углы 8'0" , 6'0". Про отрицательные углы даже не задумывался, вот переделанный с truncate.

(defun decimal-deg-to-dms (n)
  (setq d (round (truncate n)))
  (setq m (round (truncate (* (- n d) 60))))
  (setq s (round (- (* 3600 (- n d)) (* 60 m))))
  (format "%d° %d' %d''" d m s))

(decimal-deg-to-dms -90.664631042351755)   "-90° -39' -53''"
saufesma
() автор топика
Ответ на: комментарий от Siborgium

Об этом вам уже не первую тему об этом говорят. setq без нужды – плохой код.

Не знаю что ответить.

saufesma
() автор топика
Ответ на: комментарий от saufesma
(decimal-deg-to-dms -90.664631042351755)   "-90° -39' -53''"

Ну и как бы это и хорошо в таком виде. В принципе получается, что в такой форме можно в перспективе делать арифметику углов без того, чтобы задумываться о знаке угла, записанного в трех компонентах. Покомпонентно складывать углы, вычитать углы (с учетом переполнения, конечно же).

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Покомпонентно складывать углы, вычитать углы (с учетом переполнения, конечно же).

А вот так далеко я даже не думал. Тогда надо widget и оформлять всё как утилу для счёта углов. Наверное так с таким замахом.

saufesma
() автор топика
Ответ на: комментарий от saufesma

(round (truncate

round никакой не нужен. После truncate уже integer.

(truncate ARG &optional DIVISOR)

Truncate a floating point number to an int.
Rounds ARG toward zero.
With optional DIVISOR, truncate ARG/DIVISOR.
Zubok ★★★★★
()
Ответ на: комментарий от Zubok

(decimal-deg-to-dms -90.664631042351755) "-90° -39' -53""

Только всё равно где-то косячок

(defun dms-to-decimal-deg (d m s)
  (+ d
     (/ m 60.0)
     (/ s 3600.0)))

(dms-to-decimal-deg -90 -39 -53)    -90.66472222222222
saufesma
() автор топика
Ответ на: комментарий от saufesma

Потому что ты (оскорбляю чувства) округлял секунды и восстанавливаешь угол из округленного значения фактически. Чего ты ожидаешь?

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Тупо переписал

[code] (defun decimal-deg-to-dms (n) (setq d (truncate n)) (setq m (truncate (* (- n d) 60))) (setq s (truncate (- (* 3600 (- n d)) (* 60 m)))) (format «%d° %d’ %d''» d m s))

(decimal-deg-to-dms -90.664631042351755) «-90° -39’ -52''»

должно же быть «-90° -39’ -53''» [/code]

мне надо сидеть с мануалом и вспоминать, что там да как.

saufesma
() автор топика
Ответ на: комментарий от Zubok
(defun decimal-deg-to-dms (n)
  (setq d (truncate n))
  (setq m (truncate (* (- n d) 60)))
  (setq s (round (- (* 3600 (- n d)) (* 60 m))))
  (format "%d° %d' %d''" d m s))

(decimal-deg-to-dms -90.664631042351755) "-90° -39' -53''"

(defun dms-to-decimal-deg (d m s)
  (+ d
     (/ m 60.0)
     (/ s 3600.0)))

(dms-to-decimal-deg -90 -39 -53)     -90.66472222222222


-90.664631042351755 не равно -90.66472222222222

saufesma
() автор топика
Ответ на: комментарий от Zubok

Ну и [code] (decimal-deg-to-dms -90.664631042351755) «-90° -39’ -53''»

(decimal-deg-to-dms -90.66472222222222) «-90° -39’ -53''» [/code]

saufesma
() автор топика
Ответ на: комментарий от saufesma

(decimal-deg-to-dms 0.1336111111111111) «0° 8’ 1"»

У тебя фундаментальное непонимание. Я не знаю, что с этим делать. Все здесь правильно. Число очень хорошо раскладывается. Округление секунд тут на уровне самых младших значащих разрядов мантиссы получается. Число такое везучее. В примере с "-90° -39’ -53"" совсем все не так.

https://en.wikipedia.org/wiki/Double-precision_floating-point_format

UPD Сделай так: (decimal-deg-to-dms 0.1336111111111112) -> «0° 8’ 1"» и вся идиллия развалится.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 4)
Ответ на: комментарий от Zubok

Число такое везучее.

нет, просто сначала

(dms-to-decimal-deg 0 8 1) 0.1336111111111111
а уже потом
(decimal-deg-to-dms 0.1336111111111111) «0° 8’ 1''»
для любых углов работает.

В примере с "-90° -39’ -53"" совсем все не так.

Знаю, просто забуксовал.

saufesma
() автор топика
Ответ на: комментарий от saufesma

нет, просто сначала

Не нет, а да. Число везучее, так как округления практически не получается. Единица у тебя получается из оставшегося 0.9999999999999600.

В общем, так. Если хочешь поточнее, то можешь оставлять секунды неокругленными.

https://en.wikipedia.org/wiki/Decimal_degrees#Example

Note that with this formula only D can be negative and only S may have a fractional value.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Ну тебя прёт. Конечно программирование требует таких знаний.

Вот приведу аналогию. По ГОСТ 3325-85 рассчитал допуск соосности вала, для подшипника нормального класса точности, получил 0.0056 мм, длина вала 1000 мм. Показал знакомому технологу, он сказал что это теоретическая цифра в реалиях не достижимая на обычных заводах, а вот про практическую цифру он промолчал, хотя все обычные заводы делают валы. У всех размеров подшипников нормального класса точности допустимый перекос колец 8 минут. И допуск соосности вала будет лежать в тысячных.

saufesma
() автор топика
Последнее исправление: saufesma (всего исправлений: 4)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.