Как вычислить плавающую запятую в системе счисления, отличной от 10?

StackOverflow https://stackoverflow.com/questions/932263

Вопрос

Учитывая статью в Википедии о Радикс-Пойнт, как можно вычислить двоичный эквивалент 10,1 или шестнадцатеричный эквивалент 17,17?Что такое двоичный эквивалент десятой части?Для последнего шестнадцатеричное представление 17/100?

Я больше ищу алгоритм, чем решения только этих двух примеров.

Это было полезно?

Решение

Чтобы преобразовать десятичное число 10,1 в двоичное, разделите целую и дробную части и преобразуйте каждую отдельно.

Чтобы преобразовать целую часть, используйте повторное целочисленное деление на 2, а затем запишите остатки в обратном порядке:

10/2 = 5, остаток 0

5/2 = 2 остаток 1

2/2 = 1 остаток 0

1/2 = 0 остаток 1

Отвечать:1010

Чтобы преобразовать дробную часть, используйте многократное умножение на 2, вычитая целую часть на каждом шаге.Целые части в порядке генерации представляют ваше двоичное число:

0.1 * 2 = 0.2

0.2 * 2 = 0.4

0.4 * 2 = 0.8

0.8 * 2 = 1.6

0.6 * 2 = 1.2

0.2 * 2 = 0.4

0.4 * 2 = 0.8

...(цикл повторяется вечно)

Таким образом, десятичное 0,1 — это двоичное 0,000110011001100...

(Более подробное объяснение см. в процедурах dec2bin_i() и dec2bin_f() в моей статье. http://www.exploringbinary.com/base-conversion-in-php-using-bcmath/ .)

Для шестнадцатеричного числа используйте ту же процедуру, за исключением того, что делитель/множитель равен 16 вместо 2.Остатки и целые части больше 9 необходимо преобразовать непосредственно в шестнадцатеричные цифры:10 становится А, 11 становится Б,..., 15 становится F.

Другие советы

Конечное число (число, которое может быть представлено конечным числом цифр) n1 в базе б1, может оказаться непрерывным числом в другой системе счисления b2.И наоборот, неконцевое число по одной базе b1 может оказаться конечным числом по основанию b2.

Число 0,110 при преобразовании в двоичный формат является непрерывным числом, как и 0,17.10 при преобразовании в шестнадцатеричное число.Но конечное число 0,13 в системе счисления 3 при преобразовании в систему 10 представляет собой непрерывное повторяющееся число 0.(3)10 (что означает, что цифра 3 повторяется).Аналогично, конвертируя 0,110 в двоичный и 0,1710 в шестнадцатеричном формате, в итоге получаются бесконечные повторяющиеся числа 0,0 (0011).2 и 0,2(В851Е)16

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

Алгоритм довольно прост, но на практике вы можете внести множество изменений как в таблицы поиска, так и в журналы, чтобы ускорить его.Но для базового алгоритма вы можете попробовать что-то вроде этого:

shift=0;

while v>=base,  v=v/base, shift=shift+1;  

Next digit: 
if v<1.0 && shift==0, output the decimal point
else 
   D=floor(v)
   output D
   v=v-D
v=v*base
shift = shift-1
if (v==0) exit;
goto Next Digit

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

«Двоичный эквивалент» одной десятой составляет половину, т.е. вместо 1/10^1 это 1/2^1.

Каждая цифра представляет степень двойки.Цифры за точкой системы счисления одинаковы, просто они обозначают 1 в степени двойки:

 8 4 2 1 . 1/2 1/4 1/8 1/16 

Итак, для 10.1 вам, очевидно, нужны «8» и «2», чтобы составить 10-ю часть.1/2 (0,5) — слишком много, 1/4 (0,25) — слишком много, 1/8 (0,125) — слишком много.Нам нужна 1/16 (0,0625), что даст нам 0,0375.1/32 — это 0,03125, поэтому мы можем принять и это.На данный момент у нас есть:

 8 4 2 1 . 1/2 1/4 1/8 1/16 1/32
 1 0 1 0    0   0   0   1     1

С ошибкой 0,00625.1/64 (0,015625) и 1/128 (0,0078125) слишком много, 1/256 (0,00390625) подойдет:

 8 4 2 1 . 1/2 1/4 1/8 1/16 1/32 1/64 1/128 1/256
 1 0 1 0    0   0   0   1     1    0   0     1

С ошибкой 0,00234375.

.1 не может быть точно выражено в двоичном виде (так же, как 1/3 не может быть точно выражено в десятичном формате).В зависимости от того, куда вы поместили систему счисления, вам в конечном итоге придется остановиться, возможно, округлить, и признать ошибку.

Прежде чем я займусь этим в свете моей библиотеки GMP, я попытаюсь сделать PHP-код Рика Ригана универсальным для любой системы счисления от 2 до 36.

Function dec2base_f(ByVal ddecimal As Double, ByVal nBase As Long, ByVal dscale As Long) As String
    Const BASES = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" 'up to base 36
    Dim digitCount As Long
    Dim wholeNumber As Double
    Dim digit As String * 1
    digitCount = 0
    dscale = max(dscale, Len(CStr(ddecimal)) - Len("0."))
    Dim baseary_f As String
    baseary_f = "0."
    Do While ddecimal > 0 And digitCount < dscale
        ddecimal = ddecimal * nBase
        digit = Mid$(BASES, Fix(ddecimal) + 1)
        baseary_f = baseary_f & digit '"1"
        ddecimal = ddecimal - Fix(ddecimal)
        digitCount = digitCount + 1
    Loop
    dec2base_f = baseary_f
End Function

Function base2dec_f(ByVal baseary_f As String, nBase As Double) As Double
    Const BASES As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    Dim decimal_f As Double
    Dim i As Long
    Dim c As Long
    For i = Len(baseary_f) To Len("0.") + 1 Step -1
        c = InStr(BASES, Mid$(baseary_f, i, 1)) - 1
        decimal_f = decimal_f + c
        decimal_f = decimal_f / nBase
    Next
    base2dec_f = decimal_f
End Function

Debug.Print base2dec_f(dec2base_f(0.09, 2, 200), 2) --> 0.09
Debug.Print base2dec_f(dec2base_f(0.09, 8, 200), 8) --> 0.09
Debug.Print base2dec_f(dec2base_f(0.09, 16, 200), 16) --> 0.09
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top