10 이외의 라드에서 부동 소수점을 어떻게 계산합니까?
-
06-09-2019 - |
문제
Wikipedia의 기사가 주어졌습니다 라디습니다, 10.1의 이진에 해당하는 이진을 어떻게 계산합니까? 전자의 경우 10 분의 1의 이진은 무엇입니까? 후자의 경우 17/100의 16 진수 표현?
이 두 예제에 대한 솔루션보다 알고리즘을 더 많이 찾고 있습니다.
해결책
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
... (사이클은 영원히 반복)
따라서 10 대 0.1은 이진 0.000110011001100입니다 ...
(보다 자세한 설명은 내 기사의 루틴 dec2bin_i () 및 dec2bin_f ()를 참조하십시오. http://www.exploringbinary.com/base-conversion-in-php-using-bcmath/ .)
16 진수의 경우 2 대신 16의 제수/승수를 제외하고 동일한 절차를 사용하십시오. .
다른 팁
종료 번호 (유한 한 수의 숫자로 표시 될 수있는 숫자) n1 기본 b1, 다른 기본 B에서 비 터미네이션 숫자가 될 수 있습니다.2. 반대로, 한 기본의 비 터미네이션 숫자 b1 기본 B에서 종료 숫자로 판명 될 수 있습니다.2.
숫자 0.110 이진으로 변환 된 경우 0.17과 마찬가지로 말입 횟수가 없습니다.10 16 진수로 변환 될 때. 그러나 종단 번호 0.13 베이스 3에서,베이스 10으로 변환 될 때, 비 말미지, 반복적 인 숫자 0이있다. (3)10 (숫자 3이 반복되는 것을 의미합니다). 마찬가지로 0.1을 변환합니다10 이진 및 0.17로10 16 진수로, 한 사람은 비 터미네이션, 반복 숫자 0.0 (0011)으로 끝납니다.2 및 0.2 (B851E)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 자리 후 인쇄를 중지하기 위해 테스트를 할 수도 있습니다.
10 분의 1의 '이진 등가'는 1/10^1 대신 절반, 즉 1/2^1입니다.
각 숫자는 2의 힘을 나타냅니다. radix 지점 뒤에있는 숫자는 동일합니다. 단지 2의 힘보다 1을 나타냅니다.
8 4 2 1 . 1/2 1/4 1/8 1/16
따라서 10.1의 경우 10 부분을 만들려면 '8'과 '2'가 필요합니다. 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은 10 진수로 정확하게 표현할 수 없음). 당신이 당신의 라디습니다
내 GMP 라이브러리에 비추어 볼 때 이것에 대해 twiddle을하기 전에, 여기에서 Rick Regan의 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