Шестнадцатеричная арифметика

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

Для простоты рассмотрим ситуации, когда число состоит из одной шестнадцатеричной цифры. Далее будем её обозначать буквой H. Для более ясного порядка операндов будем использовать стандартные обозначения X и Y. Цифра F убрана из рассмотрения как опасная, по крайней мере в качестве первой цифры.


Операция H + Y

YH ABCDE
0 01234
1 12345
2 23450
3 34501
4 45012
5 50123
6 01234
7 12345
8 23456
9 34567
A 45678
B 56789
C 678910
D 7891011
E 89101112
10 1021222424
11 2122232425
12 2223242526
13 2324252627
14 2425262728
15 2526272829
16 2627282930
17 2728293031
18 2829303132
19 2930313233
1A 3031323334
1B 3132333435
1C 3233343520
1D 3334352021
1E 3435202122
1F 3520212223

Вычисление идёт как шестнадцатеричное, остаток по модулю 16, а от него берётся последняя цифра. X = ((X + Y) mod 16) mod 10.
Если Y двузначное, то уже две цифры X = ((X + Y) mod 256) mod 100, а значит получается как обычное сложение, если число двузначное.
Если Y дробное, то целая часть как выше, а дробная сохраняется.


Операция X + H

В этом случае осуществляется обычное сложение, только результат нормализуется. Например: 0 + A = 10, 9 + E = 23. В случае шестнадцатеричного X см. таблицу выше.


Операция Y H

YH ABCDE
0 −10−1−2−3−4
1 −9−10−1−2−3
2 −8−9−10−1−2
3 −7−8−9−10−1
4 −6−7−8−9−10
5 −5−6−7−8−9
6 −4−5−6−7−8
7 −3−4−5−6−7
8 −2−3−4−5−6
9 −1−2−3−4−5
A 0−1−2−3−4
B 10−1−2−3
C 210−1−2
D 3210−1
E 43210
10 015141312
11 116151413
12 217161514
13 318171615
14 419181716
15 520191817
16 621201918
17 722212019
18 823222120
19 924232221
1A 025242322
1B 110252423
1C 211102524
1D 312111025
1E 413121110
1F 514131211

Выглядит похоже на X = (Y − X) mod 16, но не всегда понятно, когда берётся заём, а когда нет. Число A какое-то особенное для двузначных, для него повторяется как для однозначных, т. е. только с последней цифрой идёт операция, а потом складывается.
Для трёх- и выше значных повторяется как для двузначных, т. е. 100 − A = 90, т. е. 90 + (10 − A) + 0, 100 − B = 105, т. е. 90 + (10 − B) + 0,…, 109 − E = 111, т. е. 90 + (10 − E) + 9.


Операция H X

XH ABCDE
0 1011121314
1 90123
2 89012
3 78901
4 67890
5 56789
6 45678
7 34567
8 23456
9 12345
A 01234
B −10123
C −2−1012
D −3−2−101
E −4−3−2−10
10 01234
11 −10123
12 −2−1012
13 −3−2−101
14 −4−3−2−10
15 −5−4−3−2−1
16 −6−5−4−3−2
17 −7−6−5−4−3
18 −8−7−6−5−4
19 −9−8−7−6−5
1A −10−9−8−7−6
1B −1−10−9−8−7
1C −2−1−10−9−8
1D −3−2−1−10−9
1E −4−3−2−1−10
1F −5−4−3−2−1

Нарушения обычного вычитания только для нескольких чисел, выше и правее, начиная с B − 1, для двузначных ниже и левее A − 1B.
Кстати, особенность: когда из шестнадцатеричного числа вычитается его десятичный аналог, то ноль, на самом деле, ненормализованный. Т. е. из 4-х значного будет 0000. И это можно использовать для получения нуля в любой степени. Пример в ручном режиме:

  1. Получим цифру E документированным образом: 11КИНВК{x}ВП1К[x], или можно нестандартным: 1К×ВП
  2. Добавим порядок, который хотим получить: ВП99
  3. Затем скопируем в стек: В↑В↑СX
  4. Выполним сложение + с нулём, что по правилу X + H будет обычным сложением, т. е. получится десятичный аналог, и вычитание:

И вот мы получили 0. 99.


Операция H × Y

YH ABCDE
0 00000
1 101010100
2 202020200
3 303030300
4 404040400
5 505050500
6 606060600
7 707070700
8 808080800
9 909090900
A 000000000
B 101010100
C 202020200
D 303030300
E 404040400
10 1001001001000
11 1101101101100
12 1201201201200
13 1301301301300
14 1401401401400
15 1501501501500
16 1601601601600
17 1701701701700
18 1801801801800
19 1901901901900
1A 2002002002000
1B 2102102102100
1C 2202202202200
1D 2302302302300
1E 2402402402400
1F 2502502502500

Поразительное однообразие, почти все ведут себя как 10. Не ясно, чем так отличается E, но ноль получается и для многозначных чисел.
Для двузначных соответственно, т. е. C × 20 = 200, но E × 20 = 0.


Операция X × H

XH ABCDE
0 00000
1 01234
2 4681012
3 4142310
4 8202024
5 5011325342
6 022445040
7 1033406354
8 2044526068
9 3055647382
A 0010203040
B 0010203040
C 0010203040
D 0010203040
E 00000
10 0010203040
11 1021324354
12 0416284052
13 1411245350
14 082220504
15 990021052923922
16 000032904920920
17 010043900933934
18 020054912930948
19 030905924943962
1A 940960980020
1B 940960980020
1C 940960980020
1D 940960980020
1E 0010203040
1F 0010203040

Тут уже трудно поддаётся логике. На практике автор как-то использовал D. С одной стороны, это изображение, с другой – коэффициент 10: см. таблицу H × Y. А самое основное – это проверка битового сдвига. При умножении дробной части, содержащей 1, 2, 4, 8, как бы биты, возможен выход за диапазон, т. е. 0.5 или 1.6. Так вот, при умножении на D по указанной таблице, результат из одной цифры получался, если всё нормально, или из двух, при выходе за диапазон.

Для двухзначных результат бывает ненормализованным: обратите внимание на ведущие нули в некоторых случаях. На этом фоне 14 × E выглядит как белая ворона.


Операция H ÷ X

XH ABCDE
0 ЕГГ0ГЕГГ0ГЕГГ0ГЕГГ0ГЕГГ0Г
1 01234
2 55.566.57
3 3.33333333.666666644.33333334.6666666
4 2.52.7533.253.5
5 22.22.42.62.8
6 1.66666661.833333322.16666662.3333333
7 1.42857141.57142851.71428571.85714282
8 1.251.3751.51.6251.75
9 1.11111111.22222221.33333331.44444441.5555555
A 11.11.21.31.4
B 8.4444443|−0111.25252521.34343431.4343434
C ЕГГ0ГЕГГ0Г11.231.3
D 4.|−016.|−018.|−0111.2
E 5.2929292|−012.2929292|−015.2929292|−08.2929292|−011
10 0.|−011.|−012.|−013.|−014.|−01
11 9.090909|−010.|−010.9090909|−011.8181818|−012.7272727|−01
12 8.3333333|−019.1666666|−010.|−010.8333333|−011.6666666|−01
13 7.6923076|−018.4615384|−019.2307692|−010.|−010.7692307|−01
14 7.1428571|−017.8571428|−018.5714285|−019.2857142|−010.|−01
15 6.6666666|−017.3333333|−018.|−018.6666666|−019.3333333|−01
16 6.25|−016.875|−017.5|−018.125|−018.75|−01
17 5.8823529|−016.4705882|−017.0588235|−017.6470588|−018.2352941|−01
18 5.5555555|−016.1111111|−016.6666666|−017.2222222|−017.7777777|−01
19 5.2631578|−015.7894736|−016.3157894|−016.8421052|−017.368421|−01
1A 5.|−015.1|−016.3157894|−016.1|−017.|−01
1B 5.0330001|−016.|−017.0001032|−017.8330001|−018.2330001|−01
1C 6.|−017.0003809|−017.8100038|−018.1810003|−018.100038|−01
1D 7.0005899|−017.9000589|−018.|−019.0005899|−019.9000589|−01
1E 5.64|−015.90002|−016.4|−016.60002|−017.24|−01
1F 5.4000299|−015.3223099|−016.153223|−017.0002999|−017.7000299|−01

Здесь кроме случая X = 1, и некоторых двузначных это обычное деление нормализованного шестнадцатеричного числа. Пример: E ÷ 7 = 14 ÷ 7 = 2.
Правда и здесь встречаются ненормализованные числа, пример D ÷ 12, или C ÷ 11, которое на порядок меньше, чем A ÷ 11.
Встречаются и ненормализованные нули, пример: С ÷ 12, и выглядит, как указано: 0. -01. Впрочем, в косвенной адресации мы уже встречались с подобными нулями.


Операция Y ÷ H

YH ABCDE
0 9.090909|−019.9099099|−014.44444439.9099099|−019.9099099|−01
1 ЕГГ0Г9.099099|−019.9099099|−019.9099099|−019.9099099|−01
2 ЕГГ0Г8.4444443|−019.099099|−019.9099099|−019.9099099|−01
3 ЕГГ0Г6.4444443|−01ЕГГ0Г9.099099|−019.9099099|−01
4 ЕГГ0Г4.4444443|−01ЕГГ0Г8.|−019.099099|−01
5 ЕГГ0Г2.4444443|−01ЕГГ0Г0.|−012.929292|−02
6 ЕГГ0Г6.4444443|−01ЕГГ0Г2.|−013.2929292|−01
7 ЕГГ0Г4.4444443|−01ЕГГ0Г4.|−016.2929292|−01
8 ЕГГ0Г2.4444443|−01ЕГГ0Г09.2929292|−01
9 ЕГГ0Г0.4444443|−01ЕГГ0Г2.|−012.2929292|−01
A 18.4444443|−01ЕГГ0Г4.|−015.2929292|−01
B 1.11ЕГГ0Г6.|−012.2929292|−01
C 1.21.252525218.|−015.2929292|−01
D 1.31.34343431.2318.2929292|−01
E 1.41.43434341.31.21
10 ЕГГ0Г9.099099.90990999.90990999.9099099
11 ЕГГ0Г9.099099ЕГГ0Г9.89.0292929
12 ЕГГ0Г9.099099ЕГГ0Г09.3292929
13 ЕГГ0Г9.099099ЕГГ0Г0.29.6292929
14 ЕГГ0Г9.099099ЕГГ0Г0.49.9292929
15 ЕГГ0Г9ЕГГ0Г90.22922929
16 ЕГГ0Г9.2525252ЕГГ0Г9.20.5292929
17 ЕГГ0Г9.3434343ЕГГ0Г9.49.2292929
18 ЕГГ0Г9.4343434ЕГГ0Г9.69.5292929
19 ЕГГ0Г9.5252525ЕГГ0Г9.89.8292929
1A ЕГГ0Г9.69.99099099.99099099.9909909
1B ЕГГ0Г9.85252529.99099099.99099099.9909909
1C ЕГГ0Г9.94343439.99099099.99099099.9909909
1D ЕГГ0Г0.03434349.99099099.99099099.9909909
1E ЕГГ0Г9.0990999.99099099.99099099.9909909
1F ЕГГ0Г7.44444439.99099099.99099099.9909909

Тут логики не наблюдается. Очень похожие, но разные числа: 9.099099|−01 и 9.9099099|−01, или 9.099099 и 9.9099099.
Также интересно, что при делении нуля на шестнадцатеричную цифру получается вовсе не ноль.
А самое главное, тут не просто ЕГГ0Г, а плохой ЕГГ0Г, который ранее не встречался. После его появления ПМК и в дальнейшем до выключения ПМК при выполнении многих операций всегда выдаёт ЕГГ0Г. Вот список таких операций:

+, , ×, ÷, ←→, Fsin, Fcos, Ftg, F, F1/x, Fsin-1, Fcos-1, Ftg-1, Fπ, Fx2, Fex, Flg, Fln, Fxy, F10x, F.

Ошибка возникает как в режиме вычислений, так и в программном режиме. Интересно, что F выдаёт ошибку, а FВx – нет.

Синие функции работают нормально. Видимо такой ЕГГ0Г сводит с ума только один микроконтроллер.


Результат функций над шестнадцатеричными числами

F(H)H ABCDE
Fx2 001020300
F 3.16227763.31662473.46410163.60555123.7416573
F1/x ЕГГ0Г9.099099|−019.9099099|−019.9099099|−019.9099099|−01
Fex 22026.46759874.133162754.78442413.371202604.3
F10x 1.|+101.|+0B1.|+0C1.|+0D1.|+0E
Flg 141.82368142.4027442.81635443.126564
Fln 2.302585196.30258597.63591898.58829999.302585
F 106.6631773|+412.5277867|+426.551706|+421.3383338|+43
К[x] 01234

Про более редкие операции переводов градусов/часов сказано в приложении по командам. Числа, где порядок содержит шестнадцатеричные значения, рассмотрены в разделе косвенной адресации порядок содержит шестнадцатеричные цифры.


Практическое применение

Практическое применение – это получение нестандартного результата, как отличие от обычной цифры. Или получение нестандартной последовательности. Или как был приведен выше по умножению.

Случаи с двойными и более шестнадцатеричными числами, в том числе в дробной части, не рассмотрены, как очень редко встречающиеся. Там тоже можно построить подобные таблицы, но проще посмотреть результат под конкретное число.