У меня есть двухэтапный алгоритм преобразования. Я не уверен, что это оптимальный алгоритм, но он работает довольно хорошо.
Основная идея состоит в том, чтобы начать с получения десятичного представления числа, а затем преобразовать это десятичное представление в непорядковое представление, обрабатывая четные степени и нечетные степени отдельно.
Вот пример, который мотивирует идею алгоритма. Это будет подробно описано, но в конечном итоге мы придем к алгоритму и в то же время покажем, откуда он взялся.
Предположим, мы хотим преобразовать число 0,523598734 в отрицательное десятичное число (обратите внимание, что я предполагаю, что вы можете преобразовать его в десятичное число). Заметь
0.523598734 = 5 * 10^-1
+ 2 * 10^-2
+ 3 * 10^-3
+ 5 * 10^-4
+ 9 * 10^-5
+ 8 * 10^-6
+ 7 * 10^-7
+ 3 * 10^-8
+ 4 * 10^-9
Поскольку 10^-n = (-10)^-n, когда n четно, мы можем переписать это как
0.523598734 = 5 * 10^-1
+ 2 * (-10)^-2
+ 3 * 10^-3
+ 5 * (-10)^-4
+ 9 * 10^-5
+ 8 * (-10)^-6
+ 7 * 10^-7
+ 3 * (-10)^-8
+ 4 * 10^-9
Перестановка и перегруппировка терминов дает нам следующее:
0.523598734 = 2 * (-10)^-2
+ 5 * (-10)^-4
+ 8 * (-10)^-6
+ 3 * (-10)^-8
+ 5 * 10^-1
+ 3 * 10^-3
+ 9 * 10^-5
+ 7 * 10^-7
+ 4 * 10^-9
Если бы мы могли переписать эти отрицательные члены как степени -10, а не степени 10, мы бы закончили. К счастью, мы можем сделать хорошее наблюдение: если d — ненулевая цифра (1, 2, ... или 9), то
d * 10^-n + (10 - d) * 10^-n
= 10^-n (d + 10 - d)
= 10^-n (10)
= 10^{-n+1}
Переформулировано по-другому:
d * 10^-n + (10 - d) * 10^-n = 10^{-n+1}
Таким образом, мы получаем этот полезный факт:
d * 10^-n = 10^{-n+1} - (10 - d) * 10^-n
Если предположить, что n нечетно, то -10^-n = (-10)^-n и 10^{-n+1} = (-10)^{-n+1}. Таким образом, для нечетного n мы видим, что
d * 10^-n = 10^{-n+1} - (10 - d) * 10^-n
= (-10)^{-n+1} + (10 - d) * (-10)^-n
Подумайте о том, что это означает в непорядковой системе счисления. Мы превратили степень десяти в сумму двух степеней минус десять.
Применение этого к нашему суммированию дает следующее:
0.523598734 = 2 * (-10)^-2
+ 5 * (-10)^-4
+ 8 * (-10)^-6
+ 3 * (-10)^-8
+ 5 * 10^-1
+ 3 * 10^-3
+ 9 * 10^-5
+ 7 * 10^-7
+ 4 * 10^-9
= 2 * (-10)^-2
+ 5 * (-10)^-4
+ 8 * (-10)^-6
+ 3 * (-10)^-8
+ (-10)^0 + 5 * (-10)^-1
+ (-10)^-2 + 7 * (-10)^-3
+ (-10)^-4 + 1 * (-10)^-5
+ (-10)^-6 + 3 * (-10)^-7
+ (-10)^-8 + 6 * (-10)^-9
Перегруппировка дает следующее:
0.523598734 = (-10)^0
+ 5 * (-10)^-1
+ 2 * (-10)^-2 + (-10)^-2
+ 7 * (-10)^-3
+ 5 * (-10)^-4 + (-10)^-4
+ 1 * (-10)^-5
+ 8 * (-10)^-6 + (-10)^-6
+ 3 * (-10)^-7
+ 3 * (-10)^-8 + (-10)^-8
+ 6 * (-10)^-9
В целом, это дает отрицательное десятичное представление 1,537619346ND.
Теперь давайте подумаем об этом на отрицательном уровне. Заметь
- Цифры в четных позициях в основном сохраняются.
- Цифры в нечетных позициях переворачиваются: любая ненулевая нечетная цифра заменяется на 10 минус эта цифра.
- Каждый раз, когда переворачивается нечетная цифра, предыдущая цифра увеличивается.
Давайте посмотрим на 0,523598734 и применим этот алгоритм напрямую. Мы начинаем с того, что переворачиваем все нечетные цифры, чтобы получить их 10-е дополнение:
0.523598734 --> 0.527518336
Затем мы увеличиваем четные цифры, предшествующие всем перевернутым нечетным цифрам:
0.523598734 --> 0.527518336 --> 1.537619346ND
Это соответствует нашему предыдущему номеру, так что похоже, что у нас есть задатки алгоритма!
К сожалению, все становится немного сложнее, когда мы начинаем работать с десятичными значениями, включающими число 9. Например, давайте возьмем число 0,999. Применяя наш алгоритм, мы начинаем с перестановки всех нечетных цифр:
0.999 --> 0.191
Теперь мы увеличиваем все четные цифры, предшествующие столбцу, в котором было перевернуто значение:
0.999 --> 0.191 --> 1.1(10)1
Здесь (10) указывает, что столбец, содержащий 9, переполнился до 10. Очевидно, что это недопустимо, поэтому мы должны это исправить.
Чтобы понять, как это исправить, полезно посмотреть, как считать в негабинарном коде. Вот как считать от 0 до 110:
000
001
002
003
...
008
009
190
191
192
193
194
...
198
199
180
181
...
188
189
170
...
118
119
100
101
102
...
108
109
290
К счастью, здесь действительно хороший узор. Основной механизм работает как обычное приращение по основанию 10: увеличивается последняя цифра, и, если она переполняется, перенос 1 в следующий столбец, продолжая перенос, пока все не стабилизируется. Разница здесь в том, что столбцы с нечетными номерами работают в обратном порядке. Например, если вы увеличиваете цифру -10, вы на самом деле вычитаете единицу, а не добавляете ее, поскольку увеличение значения в этом столбце на 10 соответствует включению в вашу сумму на единицу -10 меньше. Если это число становится меньше 0, вы сбрасываете его обратно на 9 (вычитая 90), а затем увеличиваете следующий столбец (добавляя 100). Другими словами, общий алгоритм увеличения отрицательного числа работает следующим образом:
- Начните с 1-й колонки.
- If the current column is at an even-numbered position:
- Add one.
- Если значение достигает 10, установите его равным нулю, а затем примените эту процедуру к предыдущему столбцу.
- If the current column is at an odd-numbered position:
- Subtract one.
- Если значение достигает -1, установите его равным 9, а затем примените эту процедуру к предыдущему столбцу.
Вы можете убедиться, что эта математика работает, обобщив приведенные выше рассуждения о цифрах -10s и 100s и поняв, что переполнение столбца с четным номером, соответствующего 10k, означает, что вам нужно добавить 10 k+1, что означает, что вам нужно уменьшить предыдущий столбец на единицу, а уменьшение значимости столбца с нечетным номером работает путем вычитания 9 10k, а затем добавления 10к+1.
Вернемся к нашему примеру. Мы пытаемся преобразовать 0,999 в десятичную дробь, и у нас получилось
0.999 --> 0.191 --> 1.1(10)1
Чтобы исправить это, мы возьмем столбец 10 и сбросим его обратно на 0, а затем перенесем 1 в предыдущий столбец. Это столбец с нечетным номером, поэтому мы уменьшаем его значение. Это дает окончательный результат:
0.999 --> 0.191 --> 1.1(10)1 --> 1.001ND
В целом, для положительных чисел у нас есть следующий алгоритм преобразования:
- Processing digits from left to right:
- If you're at an odd-numbered digit that isn't zero:
- Replace the digit d with the digit 10 - d.
- Используя стандартный алгоритм сложения негадальных чисел, увеличьте значение в предыдущем столбце.
Конечно, отрицательные числа — это совсем другая история. С отрицательными числами нечетные столбцы верны, а четные столбцы необходимо перевернуть, так как четность (-10)k членов в суммирующем флипе. Следовательно, для отрицательных чисел вы применяете описанный выше алгоритм, но сохраняете нечетные столбцы и переворачиваете четные столбцы. Точно так же вместо увеличения предыдущей цифры при переворачивании вы уменьшаете предыдущую цифру.
В качестве примера предположим, что мы хотим преобразовать -0,523598734 в отрицательный десятичный вид. Применение алгоритма дает следующее:
-0.523598734 --> 0.583592774 --> 0.6845(10)2874 --> 0.684402874ND
Это действительно правильное представление.
Надеюсь это поможет!
person
templatetypedef
schedule
13.07.2015