1*10^2 + 2*10^1 + 8*10^0 = 128
8진수 144 => 1*8^2 + 4*8^1 + 4*8^0 = (10진수 100)
16진수 64 => 6*16^1 + 4*16^0 = (10진수 100)
2진수 1100100 => 1*64 + 1*32 + 0*16 + 0*8 + 1*4 + 0*2 + 0*1 = (10진수 100)
->컴퓨터에서 16진수나 10진수를 쓰는 이유는? 2진수를 쓰고 싶으나 숫자가 너무 커지면 관리하기 어렵기 때문에
<정수 리터럴>
10진수 : 일반적으로 값을 알려주고싶을 때 사용.
8진수 : 코드에서는 거의 사용하지 않는다.
2진수 : 메모리 상태를 알려주고싶을 때 사용.
16진수 : 2진수로 표기할 시, 너무 길어지기때문에 주로 16진수로 표기.
코드 작성 시에는 주로 10진수로 표기.
간혹 메모리 상태에 집중하라고 강조하고싶을 때 2진수 사용.
정수를 표기할 때 크기에 따라 표기 방법이 다르다. 그냥 작성 시 4바이트 크기의 정수를 의미함.
표현가능한 수 : 2n-1, n은 자릿수. ex) = 8이고 -1하면 7이므로 3비트로
표현할 수 있는 크기인 7임.
4바이트(32bit) 메모리가 표현 가능한 수
양수 : 2147483647
음수 : -2147483648
이 이상의 수를 표기하려하면 컴파일에러가 나는데 이는 메모리가 넘치기 때문이며 표현하기 위해서는 8바이트 크기로 만들어주면 된다. (숫자 마지막에 L이나 l 추가)
8바이트(64bit) 메모리가 표현 가능한 수
자바에서는 각 데이터 유형에 따라 최소/최대값을 알아볼 수 있는 특별한 명령을 제공. => Integer.MAX_VALUE, Integer.MIN_VALUE etc.. Integer부분은 데이터타입 부분.
양수 : 9223372036854775807
음수 : -9223372036854775808
즉, 다음과 같은 차이점을 가진다.
100 : 4 byte
100L : 8 byte
<자릿수 표기>
자릿수표기는 _를 사용하여 읽기 쉽도록 자릿수를 표시할 수 있다. 작성하는 위치는 개발자 마음대로.
단 표기할 숫자 맨앞에 위치할 수는 없다.
<자바가 정수 리터럴을 메모리에 저장하는 방법>
정수를 2진수로 표현한다. 이하 그 방법.
부호-크기/절대값(Sign-Magnitude)
맨 왼쪽의 1비트를 부호(Sign)로 사용한다. ( 0 : 양수, 1: 음수 )
2번째 비트부터는 절대값(Magnitude)을 저장한다.
즉, 8비트인 경우 부호 1비트 + 절대값 7비트로 구성된다.
단, 문제로는 양의 0, 음의 0의 총 2개의 0이 존재하고 양수와 음수의 덧셈 시 잘못된 값이 나온다.
(8비트기준 0000 0000, 1000 0000) / (0001 + 1001) (1 +(-1))= 1010 (-2)
->사인 매그니 튜드 방법은 에러가 난다
2) 1의 보수 - 결과값의 비트를 반대로 바꾸는 방법.
모든 비트를 반대값으로 바꾸는 방법. 음수를 쉽게 계산하는 방법은 양수로 구한 후 뒤집기.
하지만 이것도 두 개의 0이 있는 문제점을 갖고 두 수를 더한 후 비트크기를 초과한 1값을 다시 더해야한다.
( 정상값에서 1이 부족한 형태로 반환되기에)
3) 2의 보수
1의 보수의 결과에 미리 1을 더해 계산하는 방법으로 음수 0을 제거한 방법.
최대비트수를 넘어서는 올림값이 발생하는 경우 그 값은 버린다.
방법 1 : 모든 비트를 반대값으로 만든 후 1을 더한다. (1의 보수에 +1하는 방법)
0010 1001 => 1101 0110 +1 : 1101 0111
방법 2 : 오른쪽에서부터 1을 찾는다. 그 후 찾은 1의 왼쪽편에 있는 모든 비트를 반대값으로 만듬.
0010 1001인 경우 : 마지막이 1이므로 마지막 1을 제외한 모든 수를 뒤집는다.
=>1101 0111이 된다.
방법 3 : 2^n에서 음수의 값만큼을 제한다.
찾으려는 값이 8비트 -41인 경우 : 28 = 256이므로 256 -41 : 215
이진화는 10진수(여기선 215)를 이진수로 만들듯이 하면 된다.
이진화된 값은 1101 0111이며 이는 1*107+1*106+1*104+1*102+1*101+1*100임
4) K 초과
표현하려는 값에 K(bias)를 더하는 방법. 바이어스는 K=2n-1로 구한다.
8bit인 경우 K = 28-1=27 = 128, 결과는 K + V이다. ( V는 찾으려는 값)
128 + 127 = 255 => 1111 1111
128 + 126 = 254 => 1111 1110
128 + 125 = 253 => 1111 1101
…
128 + 1 = 129 => 1000 0001
128 + 0 = 128 => 1000 0000 // 음수 0
128 + (-1) = 127 => 0111 1111
…
128 + (-126) = 2 => 0000 0010
128 + (-127) = 1 => 0000 0001
128 + (-128) = 0 => 0000 0000 // 양수 0
이것도 10진수를 2진화하듯이 하면 된다.
정수를 저장할 때 2의 보수 방법을 사용
부동소수점 저장
가수부 : ‘Sign-Magnitude’
지수부 : ‘Excess-K’
1000 0001
0000 1111
<부동소수점 표현>
소수점의 위치를 움직인다하여 “부동소수점”이라고 한다.
유효자리수
Exponential
숫자e지수 로 표현한다. ex) 0.0314e2 => 0.0314 * 102, - 314e-2 => 0.314 * 10-2, 같은 표현
<부동소수점이 메모리에 저장되는 원리 >
어떤 값이든 2진수로 표현할 수 있다면 메모리에 bit로 저장할 수 있다.
부동소수점을 2진수로 변환하는 것 : 정규화, 표현하는 법칙을 정의한 문서 : IEEE-754
<IEEE-754>
부동소수점을 32비트와 64비트로 표현하는 방법에 대해 정의.
32비트 표현 방법 : 단정도(Single-precision)
[ 부호비트(1) ] [ 지수부(8) ] [ 가수부(23) ] = 총 32bit
64비트 표현 방법 : 배정도(Double-precision)
[ 부호비트(1) ] [ 지수부(11) ] [ 가수부(52) ] =총 64bit
부호비트는 양수 0, 음수 1로 표기한다.
지수부는 2의 지수값에 127을 더한 값을 사용한다.
가수부는 single-magnitude 방식으로 저장하며 소수점을 기준으로 우측값만 사용한다.
만약 남는 비트가 있다면 0으로 채워넣는다.
부 | 정규화방법 |
지수 | 소수점 기준 왼쪽값은 10진수를 2진수화한다. ex) 12 = 1100 |
가수 | 소수점 기준 우측값을 2로 곱하여 나온 결과에서 정수부만을 차례대로 표기. ex) 0.375
위에서 나온 숫자를 차례대로 기술하면 011이 되며, 결과값은 0. 011이 된다. |
정규화 | 소수점의 위치를 조정하여 가수부와 지수부를 분리한다. IEEE 754 명세는 다음과 같은 형식으로 가수부와 지수부를 나눈다. 1.x1x2x3x4...x23(2진수) * 2^e처럼 소수점 왼쪽에 1만 남도록 소수점을 이동한다. 소수점 왼쪽은 무조건 1이기 때문에 저장하지 않고 버린다. 따라서 소수점 오른쪽 수만 가수부에 놓는다. 즉 x1, x2 등은 가수부 1번 비트부터 23번 비트까지를 의미한다. 23번 비트까지 채우지 못하면 나머지 비트는 0으로 채운다. ex) 1100.011(2진수)가 있을 때, 왼쪽에는 1만 남겨두기 위해 소수점을 왼쪽으로 3번 이동시킨다. = 1.100011(2진수)*23 왼쪽에 1만 남았기때문에 소수점 왼쪽은 전부 버린다. 이로 생성된 가수부는 소수점 오른쪽인 100011(2진수)이다. 지수부는 10진수로 이동횟수에 바이어스값을 더한 뒤 10진수를 2진화한다. 지수부의 최대 비트수까지 다 채우며, 만약 채울 값이 없는 경우 0으로 마저 채운다. 생성된 지수부 : 3 + 127(bias) = 130(10진수) = 10000010(2진수) Q. 바이어스는 왜 127인가? 고정값인가? |
32비트(4바이트) - 7자리까지는 거의 저장 가능. - 단정도
64비트(8바이트) - 15자리까지는 거의 저장 가능. - 배정도
부동소수점은 연산 중 해당 자료형이 처리할 수 있는 표현범위 이상의 자릿수가 결과값으로 나올경우 컴파일 할 때 에러가 나지 않고 값만 잘리기에 조심해야 함.
IEEE-754 규격에 따라 부동소수점을 2진수로 바꾸다보면 정확하게 2진수로 떨어지지않는 경우가 있는데 이것은 컴퓨터나 컴파일러, JVM 등의 문제가 아닌 IEEE-754의 문제.
해결하기 위해서는 시스템에서 필요한만큼 소수점 이하 자릿수를 적절히 잘라서 사용해야한다.
<문자 리터럴>
소스코드에 10진수가 아닌 16진수가 있다면 그건 개발자가 의도적으로 값이 아닌 2진수를 강조하기위함.
ex) System.out.println(0x41);
(이어서) 해당 숫자가 단순한 정수값이 아닌 문자코드값임을 알려주면 출력메소드는 그 문자 코드에 해당하는 문자를 폰트파일에서 찾아 출력한다.
ex) System.out.println((char) 0x41);
문자의 코드값을 알고있을 경우 코드값을 통해 문자를 출력할 수 있다.
모를 때는 특별한 기호(‘ ‘)를 사용하여 문자를 표기. => int로 강제캐스팅하면 코드값꺼냄
특수문자를 입력할 수 없는 경우 작은따옴표 사이에 특수문자의 유니코드값을 넣어도 된다. 단, 코드값 앞에는 \u를 붙여야 한다.
문자 : 2byte 사용, 음수가 없기 때문에 0부터 65535까지의 크기를 가짐.
<논리 리터럴>
true, false 두 개의 상태를 가진다.
비교 연산의 결과는 논리값.
개별적으로 논리값을 표현할 때는 4바이트 메모리에 보관.
여러 개의 논리값을 배열에 보관할 때는 각 논리값을 1바이트 메모리에 보관.
'프로그래밍 > 이론' 카테고리의 다른 글
변수 (0) | 2018.05.30 |
---|---|
컴파일러와 바이트코드 (0) | 2018.05.30 |
문자 2진화와 한글처리 특징 (0) | 2018.05.30 |