프로그래밍 언어로 기초 수학을 효율적으로 평가하는 방법은 무엇입니까?


22

프로그래밍 배후의 이론에 점점 더 많이 관여함에 따라, 나는 단순한 것처럼 보이는 것들에 매료되고 어리석은 것을 발견한다. 나는 대다수의 기본 프로세스에 대한 나의 이해가 순환 논리를 통해 정당화된다는 것을 깨닫는다.

Q : 어떻게 작동합니까?

A : 그렇기 때문에!

나는이 실현이 싫다! 나는 지식을 사랑하고 그 위에 학습을 좋아하는데, 이것이 저의 질문으로 이어집니다 (넓은 질문이지만).

의문:

기본 수학 연산자는 프로그래밍 언어로 어떻게 평가됩니까?

현재의 방법이 어떻게 개선 되었습니까?

var = 5 * 5; 

내 해석 :

$num1 = 5; $num2 = 5; $num3 = 0;
while ($num2 > 0) {
    $num3 = $num3 + $num1;
    $num2 = $num2 - 1;
}
echo $num3;

이것은 매우 비효율적 인 것 같습니다. 요인이 높을수록이 방법은 매우 느리지 만 표준 내장 방법은 즉각적입니다. 덧셈을 반복하지 않고 곱셈을 어떻게 시뮬레이트합니까?

var = 5 / 5;

이것은 어떻게 이루어 집니까? 말 그대로 5를 5 등분으로 나누는 방법을 생각할 수 없습니다.

var = 5 ^ 5; 

덧셈의 ​​반복? 내 해석 :

$base = 5;
$mod = 5;
$num1 = $base;
while ($mod > 1) {

    $num2 = 5; $num3 = 0;
    while ($num2 > 0) {
        $num3 = $num3 + $num1;
        $num2 = $num2 - 1;
    }
    $num1 = $num3;
    $mod -=1;
}
echo $num3;

다시 말하지만, 이것은 매우 비효율적이지만 다른 방법으로는 생각할 수 없습니다. 이 같은 질문은 자동적으로 처리되는 모든 수학 관련 함수로 확장됩니다.


1
나에 대한 약간의 배경 이야기, 나는 컴퓨터 과학을 위해 대학으로 향하고 나중에 철학과 이론 물리학뿐만 아니라 생명 수학 이론으로 향하고 있습니다. 많은 포부, 작은 시간.
Korvin Szanto

10
en.wikipedia.org/wiki/Category:Computer_arithmetic의 모든 링크를 본 것으로 가정해도 안전 합니까?
JB King

2
기본적으로, 그것은 당신이 초등학교에서 여러 자리 곱셈과 긴 나누기를하는 방법과 비슷합니다. A의 한 자리 숫자에 B를 곱한 값을 취하십시오. 10을 시프트하십시오. A의 다음 자릿수에 B를 곱한 값을 취하십시오. 모든 자릿수에 대해 반복하여 모두 더하십시오. 이진수이기 때문에 한 자리 곱셈이 더 간단하고 (x0 또는 x1 임) 10만큼 이동하는 대신 두 배가됩니다. 사단도 비슷합니다.
Monica에 관한 질문

답변:


35

컴퓨터 내에서 산술이 어떻게 작동하는지 이해하려면 어셈블리 언어로 프로그래밍해야합니다. 단어 크기가 작고 곱셈과 나눗셈 명령이없는 것이 바람직합니다. 6502와 같은 것.

6502에서 거의 모든 산술은 Accumulator라는 레지스터에서 수행됩니다. 레지스터는 프로세서 내에서 빠르게 액세스 할 수있는 특수 메모리 위치입니다. 따라서 두 개의 숫자를 추가하려면 첫 번째 숫자를 누산기에로드 한 다음 두 번째 숫자를 추가하십시오.

그러나 그것은 지나치게 단순화되어 있습니다. 6502는 8 비트 프로세서이므로 0에서 255까지의 숫자 만 처리 할 수 ​​있습니다. 대부분의 경우 더 큰 숫자로 작업 할 수 있습니다. 한 번에 8 비트 씩 청크를 추가해야합니다. 프로세서에는 두 개의 숫자를 추가 한 결과 누산기가 오버플로 될 때 설정되는 캐리 플래그가 있습니다. 프로세서는 덧셈을 할 때이를 추가하므로 가장 낮은 바이트의 숫자로 시작한다고 가정하면 "1을 수행"하는 데 사용될 수 있습니다. 6502의 멀티 바이트 추가는 다음과 같습니다.

  1. 클리어 캐리 플래그 (CLC)
  2. 첫 번째 숫자의 최하위 바이트로드 (LDA,로드 누산기)
  3. 두 번째 숫자의 최하위 바이트 추가 (ADC, 캐리와 함께 추가)
  4. 결과의 최하위 바이트 저장 (STA, 상점 누산기)
  5. 순차적으로 상위 바이트로 2-4 단계를 반복하십시오.
  6. 마지막에 캐리가 설정되면 넘친 것입니다. 오류 메시지 생성과 같은 적절한 조치를 취하십시오 (BCS / BCC, 캐리 세트 / 클리어시 분기)

뺄셈은 캐리를 먼저 설정하고 ADC 대신 SBC 명령어를 사용한다는 점을 제외하고 비슷합니다. 마지막에는 언더 플로가 있으면 캐리가 명확 합니다.

하지만 기다려! 음수는 어떻습니까? 6502와 함께 이들은 2의 보수라고하는 형식으로 저장됩니다. 8 비트 숫자를 가정하면 -1은 255로 저장됩니다. 무언가에 255를 추가하면 누산기 (하나는 캐리)에 1이 적기 때문입니다. -2는 254로 저장되며, -128까지 128까지 저장됩니다. 부호있는 정수의 경우 바이트의 0-255 범위의 절반은 양수에, 절반은 음수에 사용됩니다. 이 규칙을 사용하면 숫자의 높은 비트를 확인하여 음수인지 확인할 수 있습니다.

24 시간제 시계로 생각하십시오. 시간에 23을 추가하면 1 시간이 더 빨라집니다 (다음 날). 따라서 23은 -1에 해당하는 모듈 식 시계입니다.

1 바이트 이상을 사용하는 경우 음수에 더 큰 숫자를 사용해야합니다. 예를 들어, 16 비트 정수의 범위는 0-65536입니다. 65535는 -1을 나타내는 데 사용됩니다.

6502에는 더하기, 빼기, 2 곱하기 (왼쪽 이동) 및 2 나누기 (오른쪽 이동)의 네 가지 산술 연산 만 있습니다. 이항을 다룰 때 이러한 연산 만 사용하여 곱셈과 나눗셈을 수행 할 수 있습니다. 예를 들어 5 (2 진 101)와 3 (2 진 11)을 곱하는 것을 고려하십시오. 10 진수 곱하기와 마찬가지로 곱셈기의 오른쪽 자릿수로 시작하고 101에 1을 곱하여 101을 곱합니다. 그런 다음 곱셈을 왼쪽 으로 곱하고 1010을 1로 곱하여 1010을 제공합니다. 그런 다음 이 결과를 더하여 1111을 제공합니다. 15. 1이나 0 만 곱하기 때문에 실제로 곱하지는 않습니다. 승수의 각 비트는 단순히 (시프트 된) 승수를 추가 할 것인지 아닌지를 알려주 는 플래그 역할을합니다 .

나눗셈은 이진수를 제외하고 시험 분할을 사용하는 수동 긴 나눗셈과 유사합니다. 상수로 나누면 뺄셈과 비슷한 방식 으로이 작업을 수행 할 수 있습니다 .X로 나누는 대신 원하는 결과와 오버플로를 생성하는 미리 계산 된 1 / X의 변환을 곱합니다. 오늘날에도 이것은 분할보다 빠릅니다.

이제 어셈블리에서 부동 소수점 수학을 수행하거나 어셈블리에서 부동 소수점 숫자를 멋진 출력 형식으로 변환하십시오. 또한 1979 년이고 클럭 속도는 1MHz이므로 가능한 효율적으로 수행해야합니다.

더 큰 단어 크기와 더 많은 레지스터를 제외하고는 오늘날에도 거의 작동하지만, 대부분의 수학은 현재 하드웨어에 의해 수행됩니다. 그러나 여전히 동일한 기본 방식으로 수행됩니다. 예를 들어, 시프트 횟수와 곱셈에 필요한 추가 수를 더하면 6809와 같은 명령이있는 초기 프로세서의 하드웨어 곱셈 명령에 필요한주기 수와 상관 관계가 있습니다. 수동으로하는 것과 거의 같은 방식으로 마이크로 코드로. (트랜지스터 예산이 더 큰 경우, 더 빠른 이동 및 추가 방법 이 있으므로 최신 프로세서는 이러한 작업을 순차적으로 수행하지 않고 단일 사이클로도 곱셈을 수행 할 수 있습니다.)


3
이봐, 매우 자세한 설명 감사합니다! 정확히 내가 원하는 것입니다! 내 수준에서 당신을 지원하는 것이 일반적으로하는 일보다 더 복잡하다는 사실을 종종 잊어 버립니다. 이것이 제가 컴퓨터 과학을 공부하고 싶은 정확한 이유입니다. 시간을 거슬러 가면 세상이 변하지 않을 것입니다. 적절한 SQL 문을 작성하는 방법 만 알고 싶습니다. 내가 조사하려고하는 것에 대해 맛 시험기를 주셨습니다.
Korvin Szanto

7
당신이 컴퓨터를 사용하면 하드웨어를보고, 또는 적어도 하드웨어 알고리즘에서 연산을 수행하는 방법을 알고 싶다면 조립, 너무 높은 아직도, 동의
JK합니다.

뭐라고. 가산기와 쉬프터가 있다는 것을 알면 소프트웨어처럼 하드웨어에 의해 제어되는 것을 쉽게 상상할 수 있으며 소프트웨어를 사용하는 것이 더 쉽습니다.
kindall

4
-1. 하드웨어 곱셈은 교대와 함께 수행되지 않았으며 현재 30 년 가까이 추가되며 많은 CPU가 한 번에 곱할 수 있습니다. Binary Multiplier자세한 내용 은 Wikipedia 기사를 확인 하십시오.
메이슨 휠러

24

결국, 기본적인 산술 연산은 하드웨어에서 수행됩니다. 보다 구체적으로, CPU에서 (또는 실제로는 그 서브 파트)

다시 말해, 전자 회로입니다. 적절한 비트를 입력으로 설정하면 적절한 비트가 출력으로 나타납니다. 기본 논리 게이트의 조합입니다.

http://en.wikipedia.org/wiki/Adder_%28electronics%29

http://en.wikipedia.org/wiki/Binary_multiplier


3
하드웨어 알고리즘은 신중하게 지정되며 하드웨어와 별도로 연구 할 수 있습니다.
S.Lott

@ S.Lott : 귀하의 의견이 혼란 스럽습니다. 나에게 알고리즘은 일련의 단계, 절차, 프로그래밍 할 수있는 단계를 포함합니다. 여기에서는 기본 산술 연산을 수행하는 전자 회로에 대해 이야기합니다. 다시 말해, 전류가 흐르는 일련의 게이트입니다. 따라서 "알고리즘"보다 "논리적"입니다. ... 나의 2 센트.
dagnelies

6
알고리즘은 "유한하고 확실하며 효과적이다"그것은 회로에서, 또는 종이와 연필로, 또는 접시 나 DNA에서 Tinkertoys 나 분자로 수행 될 수있다. 알고리즘은 무엇이든 될 수 있습니다. 전자 회로는 정의 된 알고리즘을 따라야합니다. 마술처럼 알고리즘이 필요하지 않습니다.
S.Lott

1
한 단계로만 구성된 프로세스가 "알고리즘"으로 간주됩니까? FWIW에서 전자 회로는 일반적으로 단일 단계 처리 인 진리표를 따릅니다. 진리표가 다층 게이트로 "컴파일"된다고해서 단일 단계 프로세스라는 사실을 부정하지는 않습니다.
slebetman

2
@ S.Lott :보다 적절한 첫 번째 의견은 다음과 같습니다. 하드웨어의 "논리"는 신중하게 지정되며 하드웨어와 별도로 연구 할 수 있습니다. 그리고 실제로 그렇습니다. 이진 논리 연구를 부울 대수라고합니다.
slebetman

6

이것은 Don Knuth의 The Art of Computer Programming에서 철저한 인내로 다룹니다.

더하기, 빼기, 곱하기 및 나누기에 대한 효율적인 알고리즘이 모두 자세히 설명되어 있습니다.

분할을 잘 다루는 이와 같은 내용을 읽을 수 있습니다.

http://research.microsoft.com/pubs/151917/divmodnote.pdf


5

전자 회로에 의해 피코 초 단위로 수행됩니다. 자세한 내용은 Google '하드웨어 멀티 플라이어'등을 참조하십시오. 최신 CPU는 수십 년간 지속적으로 개선 된 매우 복잡한 결과입니다.

BTW, 반복 더하기를 곱하지 않기 때문에 왜 컴퓨터가 그렇게 될 것이라고 상상할 수 있습니까?


내 질문은 함수 자체보다는 함수 뒤에있는 추론에 관한 것입니다. 프로세서에 의해 해석된다는 것을 이해합니다. 어떻게 궁금합니다. 특히 그 배후의 이론과 그것이 의사 코드로 어떻게 복제 될 수 있는가.
Korvin Szanto

1
머리에 곱셈은 기억입니다. 또한 긴 곱셈은 내가 한 방식으로 반복이 필요합니다. 계속해서 곱셈을위한 함수를 함께
하겠습니다

2
@Korvin, 내가 추천 한 책이 이것이 당신의 관심사라면 잘 될 것입니다. 또한 Harold Abelson과 Gerald Jay Sussman의 "컴퓨터 프로그램의 구조 및 해석"을 추천합니다. 이 질문들을 깊이있게 다룹니다.
Jonathan Henson

몇몇 초기 컴퓨터는 덧셈과 뺄셈 만 지원했습니다. 일부 지원 만 빼기! 따라서 x = y * z 연산은 do (z 배) {x + y}로 구현되었습니다. 마찬가지로, x = y / z는 (y> z) {x + 1; y = y-z}
James Anderson

@ 제임스 : 그들은 교대를 지원 했습니까? 나는 곱셈이 시프트와 덧셈을 통해 이루어 졌을 것으로 예상하고 나눗셈은 시프트, 비교, 빼기였습니다.
케빈 클라인

4

이것은 어떤 방법으로도 철저한 대답을하기위한 것이 아니라 구현 방법에 대한 아이디어를 제공해야합니다. 아시다시피 숫자는 이진수로 표시됩니다. 예를 들어, 컴퓨터는 숫자 5를 00000101로 나타낼 수 있습니다. 컴퓨터가 수행 할 수있는 가장 기본적인 작업은 왼쪽으로 시프트하는 것입니다. 이것은 왼쪽 10 진수로 00001010을 제공합니다. 오른쪽으로 두 번 이동하면 00010100 (십진 20)이됩니다. 숫자를 1 번 왼쪽으로 이동할 때마다 숫자가 두 배가됩니다. x가 있고 x에 17을 곱하고 싶다고 가정 해 봅시다. x를 왼쪽으로 4 번 옮긴 다음 x를 결과에 더할 수 있습니다 (16x + x = 17x). 이 방법은 숫자에 17을 곱하는 효율적인 방법입니다. 이렇게하면 반복되는 덧셈을 사용하지 않고 컴퓨터가 많은 수를 곱하는 방법에 대한 통찰력을 얻을 수 있습니다.

나눗셈은 더하기, 빼기, 오른쪽으로 이동, 왼쪽으로 이동 등의 조합을 사용할 수 있습니다. 지수로 지수를 올리는 방법에는 여러 가지가 있습니다.


명확히하기 위해 일반적으로 한 번에 두 비트 이상 씩 이동할 수 있습니다. 따라서이 4 개의 시프트 연산은 실제로 다음과 같은 하나의 연산 shl r0, 4입니다.
Caleb

4

내가 어렸을 때 나는 너무 많은 추가로 시간을 낭비하지 않고 펜과 종이로 곱하고 나누는 방법을 배웠습니다. 나중에 나는 제곱근도 그렇게 계산할 수 있다는 것을 배웠다.

대학에서 저는 12 개의 곱셈, 나눗셈 및 덧셈을 사용하여 삼각법과 로그 연산을 계산하는 방법을 배웠습니다. 그들은 그것을 테일러 시리즈라고 불렀습니다.

그 전에 아버지는 복잡한 작업이 이미 수백 개의 값으로 계산되어 표로 제시되는 책을주었습니다. 계산 된 두 값 사이의 사인 값을 원할 때 오류를 추정하는 방법에 대한 설명도있었습니다.

정수 장치, 부동 소수점 장치, GPU 및 DSP는 실리콘에서 이러한 모든 이전 기술을 구현합니다.


3

CPU가 덧셈과 곱셈을 구현하는 방법을 사용하여 디지털 처리 문제를 해결하기 위해 디지털 회로를 설계하는 방법에 대한 아이디어를 제공하려고합니다.

첫째, 프로그래밍 언어가 곱셈과 덧셈을 어떻게 효율적으로 평가 하는가 ? 대답은 간단합니다. 곱셈으로 컴파일하고 명령어를 추가합니다. 예를 들어, 다음 코드는

a = 1 + 1;
b = a * 20;

단순히 다음과 같이 컴파일됩니다.

ADD 1 1  a
MUL a 20 b

(위의 어셈블리는 단순성을 위해 존재하지 않는 가상의 CPU를위한 것입니다).

이 시점에서 위의 대답은 단순히 문제를 이동시키고 하드웨어 마술로 해결한다는 것을 알고 있습니다. 후속 질문은 분명히 그 하드웨어 마술이 어떻게 작동합니까?

간단한 문제를 먼저 살펴 보자.

먼저 우리는 익숙한 문제를 해결하면서 정기적으로 10 진수를 더합니다.

 17
+28

첫 번째 단계는 7과 8을 더하는 것입니다. 그러나 결과적으로 한 자리 이상인 15가됩니다. 그래서 우리는 1 :

(1)
 17
+28
= 5

이제 1, 1, 2를 더합니다 :

 17
+28
=45

그래서 우리는 다음과 같은 규칙을 얻습니다.

  1. 덧셈 결과가 두 자리 이상일 때, 우리는 최하위 숫자를 유지하고 최상위 숫자를 앞으로 옮깁니다.

  2. 열에 숫자가 들어간 경우 추가 할 숫자와 함께 숫자를 더합니다.

이제 기본 2-부울 대수에서 위의 규칙을 해석 할 차례입니다.

따라서 부울 대수에서는 0과 1을 더하고 = 1을 더합니다. 0과 0 = 0을 더합니다. 그리고 1과 1 = 10을 두 자리 이상으로 더하면 1이 앞으로 나옵니다.

이것으로부터 우리는 진리표를 구성 할 수 있습니다 :

a b  |  sum  carry
-------------------
0 0  |   0     0
0 1  |   1     0
1 0  |   1     0
1 1  |   0     1

이로부터 두 개의 회로 / 부울 방정식을 구성 할 수 있습니다. 하나는 합계 출력용이고 다른 하나는 캐리 출력용입니다. 가장 순진한 방법은 모든 입력을 간단히 나열하는 것입니다. 이 형식으로 아무리 크고 복잡한 것이 든 복원 할 수있는 모든 진리표 :

(AND inputs in first row) OR (AND of inputs in second row) OR ...

이것은 기본적으로 제품 형태의 합계입니다. 우리는 1을 초래하고 0을 무시하는 출력만을 봅니다.

sum = (NOT a AND b) OR (a AND NOT b)

AND OR와 NOT을 프로그래밍 언어 기호로 바꿔서 읽기 쉽도록하겠습니다.

sum = (!a & b) | (a & !b)

기본적으로 테이블을 다음과 같이 변환했습니다.

a b  |  sum  equation
-------------------
0 0  |   0   
0 1  |   1   (!a & b)
1 0  |   1   (a & !b)
1 1  |   0   

이것은 회로로 직접 구현할 수 있습니다.

                _____
 a ------------|     |
    \          | AND |-.     ____
     \  ,-NOT--|_____|  \   |    |
      \/                 `--| OR |----- sum
      /\        _____    ,--|____|
     /  `-NOT--|     |  /
    /          | AND |-`
 b ------------|_____|

이 시점에서 관찰자들은 위의 논리가 실제로 단일 테이블, 즉 우리의 진리표에 의해 요구되는 행동을 갖는 XOR 게이트로 구현 될 수 있음을 주목할 것입니다 :

                _____
 a ------------|     |
               | XOR |---- sum
 b ------------|_____|

그러나 하드웨어가 XOR 게이트를 제공하지 않는 경우 위의 단계는 AND, OR 및 NOT 게이트로 하드웨어를 정의하고 구현하는 방법입니다.

논리 게이트를 실제 하드웨어로 변환하는 방법은 사용중인 하드웨어에 따라 다릅니다. 메커니즘이 일종의 스위칭 동작을 제공하는 한 다양한 물리적 메커니즘을 사용하여 구현할 수 있습니다. 논리 게이트는 물 분사 또는 공기 퍼프 (유체)에서 트랜지스터 (전자 장치), 떨어지는 대리석에 이르기까지 모든 것으로 구현되었습니다. 그것은 그 자체로 큰 주제이기 때문에 나는 그것을 극복하고 논리 게이트를 물리적 장치로 구현할 수 있다고 말할 것입니다.

이제 캐리 신호에 대해서도 똑같이합니다. 캐리 신호가 참인 조건은 하나뿐이므로 방정식은 다음과 같습니다.

carry = a & b

따라서 캐리는 간단합니다.

                _____
 a ------------|     |
               | AND |---- carry
 b ------------|_____|

그것들을 결합하면 우리는 반 가산기라고 알려진 것을 얻습니다.

                _____
 a ------;-----|     |
         |     | XOR |---- sum
 b --;---|-----|_____|
     |   |      _____
     |   '-----|     |
     |         | AND |---- carry
     '---------|_____|

그런데 위의 회로에 대한 방정식은 다음과 같습니다.

sum = a ^ b
carry = a & b

반가산기에 무언가가 없습니다. 결과가 이월보다 두 자리 이상인 경우 첫 번째 규칙을 구현했지만 두 번째 규칙을 구현하지 않은 경우 캐리가 있으면 숫자와 함께 추가하십시오.

따라서 두 자리 이상의 숫자를 추가 할 수있는 추가 회로 인 완전 가산기를 구현하려면 진리표를 정의해야합니다.

a b c  |  sum  carry
---------------------
0 0 0  |   0     0
0 0 1  |   1     0
0 1 0  |   1     0
0 1 1  |   0     1
1 0 0  |   1     0
1 0 1  |   0     1
1 1 0  |   0     1
1 1 1  |   1     1

합계에 대한 방정식은 다음과 같습니다.

sum = (!a & !b & c) | (!a & b & !c) | (a & !b & !c) | (a & b & c)

우리는 동일한 과정을 거쳐 방정식을 분해하고 단순화하고 회로처럼 해석 할 수 있지만이 대답은 너무 길어지고 있다고 생각합니다.

이제 디지털 로직이 어떻게 설계되는지에 대한 아이디어를 얻게됩니다. Karnaugh 맵 (진실 테이블을 단순화하는 데 사용됨)과 같은 에스프레소와 같은 논리 컴파일러와 같이 언급하지 않은 다른 트릭이 있지만 (부울 방정식을 직접 계산할 필요가 없습니다) 기본은 기본적으로 위에서 설명한 :

  1. 단일 비트 (숫자) 수준에서 작업 할 수있을 때까지 문제를 분해하십시오.

  2. 진리표를 사용하여 원하는 출력을 정의하십시오.

  3. 표를 부울 방정식으로 변환하고 방정식을 단순화하십시오.

  4. 방정식을 논리 게이트로 해석하십시오.

  5. 논리 게이트를 구현하여 논리 회로를 실제 하드웨어 회로로 변환하십시오.

그것이 근본적인 (또는 오히려 저수준) 문제가 실제로 해결되는 방법입니다-많은 진실 테이블. 실제 창의적인 작업은 MP3 디코딩과 같은 복잡한 작업을 비트 수준으로 분류하여 진리표로 작업 할 수 있습니다.

곱셈을 구현하는 방법을 설명 할 시간이 없습니다. 곱셈이 얼마나 오래 작동하는지에 대한 규칙을 알아 낸 다음 이진수로 해석하여 진리표로 세분화하여 균열을 시도해 볼 수 있습니다. 또는 Wikipedia를 읽을 수 있습니다 : http://en.wikipedia.org/wiki/Binary_multiplier


2

기본 산술 명령어는 매우 효율적인 어셈블리 명령어로 수행됩니다.

보다 복잡한 (또는 추상적 인) 명령어는 루핑 메커니즘을 사용하여 조립하거나 std lib에서 처리합니다.

대학에서 수학을 공부하면서 람다 미적분학 (Lamda Calculus) 및 빅오 (Big-O) 표기법을 공부하게됩니다. 프로그래머는 이러한 모든 것 이상을 사용하여 효율적인 알고리즘을 평가하고 생성합니다. 어쨌든 기본 항목은 일반적으로 어셈블리 또는 c 포인터와 같은 낮은 수준에서 수행됩니다.

이 주제에 대한 훌륭한 소개는 Charles Petzold의 "Code"입니다.


1
또는 조회 테이블. 값을 미리 계산하고 찾아 보는 것이 훨씬 빠릅니다. 예 Sin / Cos / Tan (정수 분할이 사전 계산되어 하드웨어에 저장되지만 정수 분할).
Martin York

1

Fundamentals of Digital Logic ... 과 같은 책을 받으십시오. Freshman / Sophomore EE 학생들에게는 여전히 표준이라고 생각합니다. 그것). 그러면 가산기와 곱셈기를 살펴보고 하드웨어가 수행하는 작업의 기본 원리를 이해하기 시작할 수있는 충분한 배경 ​​지식을 얻을 수 있습니다.

당신의 대답은 단기적으로는 "그렇기 때문에"이 복잡한 행동을 불러 일으키기 위해 여러 가지 간단한 논리가 합쳐지기 때문입니다.

프로그램을 컴파일하고 실행하는 방법에 대한 모든 원칙을 이해하려는 경우이를 함께 수행하면 모든 것이 중간에서 어떻게 충족되는지 확인할 수 있습니다.


1

여기에 좋은 답변이 많이 있습니다. 올바른 아이디어부터 시작했습니다. 곱셈과 같은 복잡한 연산은 간단한 연산으로 만들어집니다. 짐작했듯이, 일련의 덧셈을 사용하는 것보다 곱셈 명령없이 곱셈을 수행하는 더 빠른 방법이 있습니다. 모든 곱셈은 더 작은 곱셈의 합으로, 또는 시프트와 덧셈의 조합으로 구현 될 수 있습니다. 예 :

a = 5 + 5 + 5 + 5 + 5;           // 5*5, but takes 5 operations
b = (5 << 2) + 5;                // 5*5 in only 2 operations
c = (41 << 4) + (41 << 2) + 41   // 41*21 in 4 operations

나눗셈도 더 작은 작업으로 나눌 수 있습니다. XOR (^)은 내가 본 모든 프로세서에 내장 된 명령어이지만, AND, OR 및 NOT의 조합으로 구현할 수도 있습니다.

그러나 프로세서가 제공하는 명령어 종류와 이러한 명령어를보다 복잡한 작업으로 결합 할 수있는 방법에 대한 일반적인 아이디어보다 구체적인 답변이 만족스럽지 않다는 느낌이 듭니다. 건강한 언어의 어셈블리 언어보다 호기심에 더 좋은 것은 없습니다. 다음은 MIPS 어셈블리 언어에 대한 매우 유용한 소개입니다.


1

최신 프로세서가 두 개의 64 비트 정수의 곱셈을 구현하는 방법은 다음과 같습니다.

당신은 긴 곱셈을 수행하는 방법을 알고 있습니다. 두 개의 10 자리 숫자를 곱하려면 하나의 10 자리 숫자에 다른 숫자의 10 자리 숫자 각각을 곱하고 11 자리 결과를 하나씩 아래에 쓰고 이동 한 다음 모든 숫자를 더합니다.

최신 프로세서는 64 x 64 비트로이 작업을 수행합니다. 그러나 두 개의 단일 비트 수의 곱셈은 매우 간단합니다. 1 x 1 = 1이며 다른 모든 제품은 0입니다. 이것은 논리적으로 구현됩니다. 결과가 두 자리가 될 수있는 10 진수 제품과 달리 단일 비트 숫자의 이진 곱은 항상 1 비트입니다.

이제 64 비트의 64 비트 행을 추가해야합니다. 그러나 64 비트 숫자의 64 개 추가는 어리 석습니다. 따라서 프로세서는 3/2 가산기 또는 7/3 가산기를 사용합니다. 단일 비트 수를 3 개 추가하면 결과는 0, 1, 2 또는 3이 될 수 있으며 두 비트에 맞습니다. 7 개의 단일 비트 숫자를 추가하면 결과는 0에서 7까지의 숫자이며 3 비트로 표시 될 수 있습니다. IBM은 18 개의 기본 회로 (PowerPC 문서)만으로 7/3 가산기를 만들 수 있다고 주장하지만 인텔과 ARM 도이 작업을 수행 할 수 있습니다.

4096 비트가 있고 동일한 비트 위치에서 약 600 개의 7 비트 그룹으로 그룹화 한 다음 약 600 개의 7/3 가산기를 사용하여 결과를 4096 비트에서 2,000 미만으로 줄입니다. 그런 다음 평범한 전체 가산기로 공급할 수있는 비트 쌍으로 끝날 때까지 반복해서 똑같이 반복합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.