Преобразование повторяющегося двоичного числа в десятичное (выражается как серия?) - PullRequest
3 голосов
/ 24 января 2010

Учитывая двоичное число, которое повторяется, например, 0. (0011) или 0.0 (101), как можно преобразовать его в десятичное число?

До сих пор мне удавалось найти простой способ преобразования конечного двоичного числа в десятичное, как показано ниже:

res(N+2) = res(N+1) / 2 + res(N)

где res - результат после шага N, а N - текущая итерация (N = 0; n -> (num двоичных цифр)). Повторное применение этого к неопределенному двоичному числу дает хорошее приближение, например

dec:0.4 || bin: 0.(0110):

0     / 2 + 0 = 0
0     / 2 + 0 = 0
0     / 2 + 1 = 1
1/2   / 2 + 1 = 3/2
3/2   / 2 + 0 = 3/4
3/4   / 2 + 0 = 3/8
3/8   / 2 + 1 = 19/16
19/16 / 2 + 1 = 51/32
51/32 / 2 + 0 = 51/64
51/64 / 2 + 0 = 51/128 = 0.3984

, что примерно равно 0,4.

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

Ответы [ 4 ]

3 голосов
/ 24 января 2010

Учитывая двоичное число, которое повторяется, например, 0. (0011) или 0.0 (101), как можно преобразовать его в десятичное?

Это можно решить (т. Е. Можно определить точное рациональное количество) в двоичном виде точно так же, как и в десятичном. В десятичном виде, если у нас есть, скажем, 0.(567), и мы хотим определить точное рациональное количество, которое оно представляет, мы просто берем 567 в качестве числителя и 999 (число, которое имеет n 9 s, где n - количество цифр в повторяющейся группе) в качестве нашего знаменателя:

0.(567) = 567/999 = 189/333 = 63/111

, который сейчас находится в самых низких условиях. Этот процесс является перегонкой полного результата бесконечной геометрической серии , упомянутого @Rick Regan .

В двоичном коде мы делаем то же самое, за исключением того, что вместо n 9 s в качестве нашего знаменателя мы хотим n 1 s (так как 1 является самой старшей цифрой в двоичном виде). Так например

0.(0011) = 0011 / 1111 =(in decimal) 3/15 = 1/5

Если у вас есть цифры перед повторяющейся группой, просто сделайте некоторую арифметику вокруг этого вычисления: например, 0.0(101) - это всего лишь 0.(101), деленное на 2. Последний - 101 / 111, или 5/7, поэтому 0.0(101) is 5/14.

1 голос
/ 24 января 2010

Один из способов получить точный ответ - использовать бесконечные геометрические ряды. Бесконечная сумма степеней дроби r для показателей 1 до бесконечности, 0 <= r <1, ​​равна r / (1-r). </p>

В вашем примере 0. (0011), 0.0011 представляет дробь 3/16. Вычтите 3, и вы получите r = 1/16. r / (1-r) = (1/16) / (15/16) = 1/15. Умножьте это на 3, которые вы учли, и получите ответ: 3/15 = 1/5 = 0,2.

1 голос
/ 24 января 2010

Даже компьютеры не совсем правильно поняли. Обычно значение просто округляется. Если вы начнете отображать значения с плавающей точкой с слишком большой точностью, вы получите странные значения, такие как 0,3984 вместо 0,4.

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

Просто продолжайте, пока не решите, что вы достаточно точны, и округлите его.

0 голосов
/ 17 января 2019

Вы можете сложить все вместе за один шаг, если вы делаете то же самое, что и в десятичном виде, используя самую большую цифру (9 в базе 10, 1 в базе 2), количество раз равное повторенным цифрам и 0, равное количество цифр перед повторными цифрами. Надеюсь, пример прояснит это:

0.196(2) = (196*9 + 2)/(9000)
0.12(034) = (12*999 + 34)/99900

b0.01(011) = (b1*b111 + b11)/b11100 = (1*7 + 3)/(7*4) = 10/28
...