Làm thế nào là toán học cơ bản được đánh giá hiệu quả bởi các ngôn ngữ lập trình?


22

Khi tôi ngày càng tham gia nhiều hơn vào lý thuyết đằng sau lập trình, tôi thấy mình bị mê hoặc và chết lặng bởi những điều tưởng chừng đơn giản .. Tôi nhận ra rằng sự hiểu biết của tôi về phần lớn các quy trình cơ bản được chứng minh thông qua logic vòng tròn

Q : Cái này hoạt động thế nào?

A : Bởi vì nó làm!

Tôi ghét nhận thức này! Tôi yêu kiến ​​thức, và trên hết tôi yêu thích việc học, điều này dẫn tôi đến câu hỏi của tôi (mặc dù đó là một câu hỏi rộng).

Câu hỏi:

Các toán tử cơ bản được đánh giá với các ngôn ngữ lập trình như thế nào?

Làm thế nào có phương pháp hiện tại đã được cải thiện?

Thí dụ

var = 5 * 5; 

Lời giải thích của tôi:

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

Điều này dường như là không hiệu quả cao. Với các yếu tố Cao hơn, phương pháp này rất chậm trong khi phương thức được xây dựng trong tiêu chuẩn là tức thời. Làm thế nào bạn sẽ mô phỏng phép nhân mà không lặp lại bổ sung?

var = 5 / 5;

Làm thế nào điều này thậm chí được thực hiện? Tôi không thể nghĩ ra một cách để chia nó thành 5 phần bằng nhau theo nghĩa đen.

var = 5 ^ 5; 

Lặp lại các lần lặp của phép cộng? Lời giải thích của tôi:

$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;

Một lần nữa, đây là TUYỆT VỜI không hiệu quả, nhưng tôi không thể nghĩ ra cách nào khác để làm điều này. Câu hỏi tương tự này mở rộng cho tất cả các chức năng liên quan đến toán học được xử lý tự động.


1
Một chút lạc quan đối với tôi, tôi đang theo học đại học về khoa học máy tính, và sau đó là lý thuyết toán học cuộc sống cũng như có thể là triết học và vật lý lý thuyết. Nhiều khát vọng, ít thời gian.
Korvin Szanto

10
Có an toàn không khi cho rằng bạn đã xem tất cả các liên kết từ en.wikipedia.org/wiki/C Category: Computer_arithatures ?
JB King

2
Về cơ bản, nó tương tự như cách bạn được dạy để thực hiện phép nhân nhiều chữ số và phép chia dài ở trường tiểu học. Lấy một chữ số của A, nhân với B. Shift bằng mười. Lấy chữ số tiếp theo của A, nhân với B. Lặp lại cho tất cả các chữ số, cộng tất cả lại với nhau. Bởi vì nó là nhị phân, phép nhân một chữ số đơn giản hơn (x0 hoặc x1) và thay vì thay đổi mười, bạn nhân đôi. Phân chia cũng tương tự.
Hỏi về Monica

Câu trả lời:


35

Để thực sự hiểu cách thức số học hoạt động bên trong máy tính, bạn cần phải lập trình bằng ngôn ngữ lắp ráp. Tốt nhất là một với kích thước từ nhỏ và không có hướng dẫn nhân và chia. Một cái gì đó giống như 6502.

Trên 6502, hầu như tất cả các số học được thực hiện trong một thanh ghi gọi là Accumulator. (Thanh ghi là một vị trí bộ nhớ đặc biệt bên trong bộ xử lý có thể được truy cập nhanh chóng.) Vì vậy, để thêm hai số, bạn tải số đầu tiên vào Accumulator, sau đó thêm số thứ hai vào nó.

Nhưng đó là quá đơn giản. Bởi vì 6502 là bộ xử lý 8 bit, nó chỉ có thể xử lý các số từ 0 đến 255. Hầu hết thời gian bạn sẽ muốn có thể làm việc với các số lớn hơn. Bạn phải thêm chúng trong các khối, 8 bit cùng một lúc. Bộ xử lý có cờ Carry được đặt khi kết quả của việc thêm hai số tràn Bộ tích lũy. Bộ xử lý cho biết thêm rằng khi thực hiện bổ sung, do đó, nó có thể được sử dụng để "mang số 1" giả sử bạn bắt đầu với byte thứ tự thấp nhất của một số. Một bổ sung nhiều byte trên 6502 trông như thế này:

  1. Xóa cờ mang (CLC)
  2. Tải byte thứ tự thấp nhất của số đầu tiên (LDA, bộ tích lũy tải)
  3. Thêm byte thứ tự thấp nhất của số thứ hai (ADC, thêm với carry)
  4. Lưu trữ byte kết quả theo thứ tự thấp nhất (STA, tích lũy cửa hàng)
  5. Lặp lại các bước 2-4 với các byte thứ tự cao hơn liên tiếp
  6. Nếu ở cuối, carry được đặt, bạn đã tràn; thực hiện hành động thích hợp, chẳng hạn như tạo thông báo lỗi (BCS / BCC, chi nhánh nếu mang / xóa)

Phép trừ cũng tương tự ngoại trừ bạn đặt carry trước, sử dụng lệnh SBC thay vì ADC và cuối cùng thì carry sẽ nếu có dòng chảy.

Nhưng chờ đã! Còn số âm thì sao? Vâng, với 6502, chúng được lưu trữ trong một định dạng gọi là bổ sung của hai. Giả sử số 8 bit, -1 được lưu dưới dạng 255, vì khi bạn thêm 255 vào một thứ gì đó, bạn sẽ nhận được một ít hơn trong Accumulator (cộng với mang theo). -2 được lưu trữ dưới dạng 254 và cứ thế, xuống đến -128, được lưu dưới dạng 128. Vì vậy, đối với các số nguyên đã ký, một nửa phạm vi 0-255 của một byte được sử dụng cho số dương và một nửa cho số âm. (Quy ước này cho phép bạn chỉ cần kiểm tra bit cao của một số để xem nó có âm hay không.)

Hãy nghĩ về nó giống như một chiếc đồng hồ 24 giờ: thêm 23 vào thời gian sẽ dẫn đến thời gian sớm hơn một giờ (vào ngày hôm sau). Vậy 23 là mô-đun của đồng hồ tương đương -1.

Khi bạn đang sử dụng nhiều hơn 1 byte, bạn phải sử dụng số lớn hơn cho âm. Ví dụ: số nguyên 16 bit có phạm vi 0-65536. Vì vậy, 65535 được sử dụng để đại diện cho -1, v.v., bởi vì thêm 65535 vào bất kỳ số nào dẫn đến kết quả là ít hơn (cộng với một lần mang).

Trên 6502 chỉ có bốn phép toán số học: cộng, trừ, nhân với hai (dịch chuyển sang trái) và chia cho hai (dịch chuyển sang phải). Phép nhân và chia có thể được thực hiện chỉ bằng các thao tác này khi giao dịch nhị phân. Ví dụ, hãy xem xét nhân 5 (nhị phân 101) và 3 (nhị phân 11). Cũng như phép nhân dài thập phân, chúng ta bắt đầu bằng chữ số bên phải của cấp số nhân và nhân 101 với 1, cho 101. Sau đó, chúng ta thay đổi phép nhân sang trái và nhân 1010 với 1, cho 1010. Sau đó, chúng ta cộng các kết quả này lại với nhau, cho 1111 hoặc 15. Vì chúng ta chỉ nhân với 1 hoặc 0, nên chúng ta không thực sự nhân lên; mỗi bit của số nhân chỉ đơn giản đóng vai trò là một cờ cho chúng ta biết có nên thêm bội số (đã thay đổi) hay không.

Phân chia tương tự như phân chia dài thủ công bằng cách sử dụng các ước số thử nghiệm, ngoại trừ trong nhị phân. Nếu bạn đang chia cho một hằng số, có thể thực hiện điều này theo cách tương tự với phép trừ: thay vì chia cho X, bạn nhân với một biểu hiện được tính toán trước 1 / X tạo ra kết quả mong muốn cộng với tràn. Ngay cả ngày nay, điều này là nhanh hơn so với phân chia.

Bây giờ hãy thử làm toán học dấu phẩy động trong lắp ráp hoặc chuyển đổi các số dấu phẩy động thành các định dạng đầu ra đẹp trong lắp ráp. Và hãy nhớ, đó là năm 1979 và tốc độ xung nhịp là 1 MHz, vì vậy bạn phải làm điều đó hiệu quả nhất có thể.

Mọi thứ vẫn hoạt động khá giống như ngày nay, ngoại trừ với kích thước từ lớn hơn và nhiều thanh ghi hơn, và tất nhiên phần lớn toán học được thực hiện bằng phần cứng bây giờ. Nhưng nó vẫn được thực hiện theo cách cơ bản tương tự. Ví dụ, nếu bạn cộng số lượng ca và thêm yêu cầu cho một số nhân, thì nó tương quan khá tốt với số chu kỳ cần thiết cho một lệnh nhân phần cứng trên các bộ xử lý sớm có lệnh như vậy, chẳng hạn như 6809, nơi nó được thực hiện trong microcode theo cách tương tự như bạn sẽ làm bằng tay. (Nếu bạn có ngân sách bóng bán dẫn lớn hơn, có nhiều cách nhanh hơn để thực hiện các ca và bổ sung, vì vậy các bộ xử lý hiện đại không thực hiện các hoạt động này một cách tuần tự và có thể thực hiện các phép nhân chỉ trong một chu kỳ.)


3
Hey, cảm ơn bạn đã giải thích rất chi tiết của bạn! Đó chính xác là những gì tôi muốn! Ở cấp độ của tôi, bạn thường quên rằng những gì đang hỗ trợ bạn thường phức tạp hơn bất cứ điều gì bạn đang làm. Đó là lý do chính xác tại sao tôi muốn học ngành khoa học máy tính. Tôi ghét thực tế là nếu tôi quay ngược thời gian, tôi sẽ không biết thế giới có gì thay đổi, chỉ là cách xây dựng một câu lệnh SQL phù hợp;) Dù sao đi nữa, cảm ơn bạn rất nhiều vì đã dành thời gian để viết ra câu trả lời này, bạn đã cho tôi một người thử hương vị vào những gì tôi sắp tìm hiểu.
Korvin Szanto

7
không đồng ý, lắp ráp vẫn còn quá cao, nếu bạn muốn biết máy tính làm số học như thế nào, bạn phải xem xét phần cứng, hoặc ít nhất là thuật toán phần cứng
jk.

Ơ. Khi bạn biết có các trình bổ sung và bộ dịch chuyển, thật dễ dàng để tưởng tượng chúng được điều khiển bởi phần cứng như bằng phần mềm và việc chơi với phần mềm sẽ dễ dàng hơn.
kindall

4
-1. Việc nhân phần cứng đã không được thực hiện với các ca làm việc và thêm gần 3 thập kỷ nay và nhiều CPU có thể nhân lên trong một chu kỳ. Kiểm tra bài viết trên Wikipedia Binary Multiplierđể biết chi tiết.
Mason Wheeler

24

Cuối cùng, các phép toán số học cơ bản được thực hiện trong phần cứng. Cụ thể hơn, trong CPU (hoặc thực tế, một phần phụ của nó)

Nói cách khác, đó là các mạch điện tử. Đặt các bit thích hợp làm đầu vào và bạn sẽ nhận được các bit thích hợp làm đầu ra. Nó là sự kết hợp của các cổng logic cơ bản.

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

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


3
Các thuật toán cho phần cứng được chỉ định cẩn thận và có thể được nghiên cứu tách biệt với phần cứng.
S.Lott

@ S.Lott: Tôi thấy bình luận của bạn khó hiểu. Đối với tôi, các thuật toán bao gồm một loạt các bước bạn làm theo, một thủ tục, một cái gì đó bạn có thể lập trình. Ở đây, chúng ta đang nói về các mạch điện tử thực hiện các hoạt động số học cơ bản. Nói cách khác, chỉ là một chuỗi các cổng nơi dòng chảy. Vì vậy, nó "hợp lý" hơn "thuật toán" tốt nhất. ... 2 xu của tôi.
dagnelies

6
Một thuật toán là "hữu hạn, xác định và hiệu quả" Nó có thể được thực hiện trong các mạch, hoặc được thực hiện bằng giấy và bút chì, hoặc được thực hiện với Tinkertoys hoặc các phân tử trong một món ăn hoặc DNA. Thuật toán có thể là bất cứ điều gì. Một mạch điện tử phải tuân theo một thuật toán xác định. Nó không kỳ diệu vượt qua sự cần thiết của các thuật toán.
S.Lott

1
Một quá trình chỉ bao gồm một bước sẽ được coi là một "thuật toán"? FWIW, các mạch điện tử thường đi theo một bảng chân lý - một bước xử lý duy nhất. Bảng chân lý cuối cùng được "biên dịch" thành các cổng nhiều lớp không phủ nhận thực tế rằng đó là một quá trình đơn lẻ.
slebetman

2
@ S.Lott: Một nhận xét đầu tiên thích hợp hơn sẽ là: "logic" của phần cứng được chỉ định cẩn thận và có thể được nghiên cứu tách biệt với phần cứng. Và thực sự nó là. Nghiên cứu về logic nhị phân được gọi là Đại số Boolean.
slebetman

6

Tất cả được bao phủ với sự kiên nhẫn kỹ lưỡng trong Nghệ thuật lập trình máy tính của Don Knuth.

Các thuật toán hiệu quả để cộng, trừ, nhân và chia đều được mô tả chi tiết đầy đủ.

Bạn có thể đọc những thứ như thế này bao gồm sự phân chia độc đáo.

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


5

Nó được thực hiện trong picoseconds bởi các mạch điện tử. Google 'hệ số nhân phần cứng', v.v. để biết chi tiết. CPU hiện đại là kết quả cực kỳ phức tạp của nhiều thập kỷ cải tiến liên tục.

BTW, vì bạn không nhân với phép cộng lặp lại, tại sao bạn lại tưởng tượng một máy tính sẽ như thế nào?


Câu hỏi của tôi liên quan đến lý do đằng sau các chức năng chứ không phải chính các chức năng, tôi hiểu rằng nó được giải thích bởi bộ xử lý, tôi tò mò làm thế nào. Cụ thể là lý thuyết đằng sau nó và làm thế nào nó có thể được sao chép trong mã giả.
Korvin Szanto

1
Phép nhân tôi làm trong đầu là trí nhớ. Phép nhân dài cũng đòi hỏi sự lặp lại theo cách mà tôi đã làm. Tôi sẽ tiếp tục và kết hợp một chức năng để nhân dài
Korvin Szanto

2
@Korvin, cuốn sách tôi giới thiệu sẽ phục vụ tốt cho bạn nếu đây là sở thích của bạn. Tôi cũng đề xuất "Cấu trúc và diễn giải các chương trình máy tính" của Harold Abelson và Gerald Jay Sussman. Nó giải quyết những câu hỏi này một cách sâu sắc.
Jonathan Henson

Một số máy tính ban đầu chỉ hỗ trợ phép cộng và phép trừ. Một số chỉ được hỗ trợ trừ! Vì vậy, thao tác x = y * z đã được triển khai như do (z lần) {x + y} phân chia tương tự x = y / z được thực hiện như while (y> z) {x + 1; y = y - z}
James Anderson

@James: họ có hỗ trợ ca không? Tôi mong đợi phép nhân được thực hiện thông qua shift và add, trong khi phép chia là shift, so sánh, trừ.
kevin cline

4

Đây không phải là một câu trả lời thấu đáo bằng bất kỳ phương tiện nào nhưng nó sẽ cung cấp cho bạn một số ý tưởng về cách mọi thứ được thực hiện. Như bạn có thể biết số được đại diện trong nhị phân. Chẳng hạn, một máy tính có thể đại diện cho số 5 là 00000101. Một thao tác rất cơ bản mà máy tính có thể làm là dịch chuyển sang trái, sẽ cho 00001010 là số thập phân 10. Nếu nó được dịch đúng hai lần thì nó sẽ là 00010100 (thập phân 20). Mỗi lần thay đổi các chữ số còn lại 1 lần, chúng tôi nhân đôi số. Giả sử tôi có một số x và tôi muốn nhân nó với 17. Tôi có thể dịch chuyển x sang trái 4 lần và sau đó thêm x vào kết quả (16x + x = 17x). Đây sẽ là một cách hiệu quả để nhân một số với 17. Điều này sẽ cung cấp cho bạn một cái nhìn sâu sắc về cách một máy tính có thể nhân số lớn mà không cần sử dụng phép cộng lặp lại.

Bộ phận có thể sử dụng kết hợp phép cộng, phép trừ, dịch chuyển sang phải, dịch chuyển sang trái, v.v ... Ngoài ra còn có nhiều thủ thuật để tăng số lên số mũ.


Để rõ ràng, bạn thường có thể thay đổi nhiều hơn một bit mỗi lần. Vì vậy, 4 hoạt động thay đổi thực sự chỉ là một hoạt động, như : shl r0, 4.
Caleb

4

Khi tôi còn là một đứa trẻ, tôi đã học cách nhân và chia bằng bút và giấy, mà không lãng phí thời gian với quá nhiều bổ sung. Sau này tôi mới biết rằng căn bậc hai cũng có thể tính toán theo cách đó.

Ở trường đại học, tôi đã học được cách tính toán các phép toán lượng giác và logarit với hàng tá phép nhân, phép chia và phép cộng. Họ gọi nó là loạt Taylor.

Trước đó, cha tôi đã cho tôi một cuốn sách trong đó các hoạt động phức tạp đó đã được tính toán cho hàng trăm giá trị và được trình bày trong bảng. Cũng có một số giải thích cho việc ước tính lỗi khi bạn muốn sin của một giá trị giữa hai giá trị được tính toán.

Các đơn vị nguyên, đơn vị dấu phẩy động, GPU và DSP chỉ thực hiện tất cả các kỹ thuật cũ trên silicon.


3

Tôi sẽ cố gắng cung cấp cho bạn ý tưởng về cách các mạch kỹ thuật số được thiết kế để giải quyết các vấn đề xử lý kỹ thuật số bằng cách sử dụng các vấn đề bạn đặt ra: làm thế nào để CPU thực hiện các phép cộng và phép nhân.

Đầu tiên, hãy đặt câu hỏi trực tiếp ra khỏi cách: làm thế nào để một ngôn ngữ lập trình đánh giá hiệu quả các phép nhân và bổ sung. Câu trả lời rất đơn giản, họ biên dịch chúng thành bội số và thêm hướng dẫn. Ví dụ: đoạn mã sau:

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

được biên dịch đơn giản thành một cái gì đó như:

ADD 1 1  a
MUL a 20 b

(lưu ý rằng phần lắp ráp ở trên dành cho CPU tưởng tượng không tồn tại, vì đơn giản).

Tại thời điểm này, bạn nhận ra rằng câu trả lời trên chỉ đơn giản là thay đổi vấn đề và giải quyết nó bằng phép thuật phần cứng. Câu hỏi tiếp theo rõ ràng là ma thuật phần cứng đó hoạt động như thế nào?

Trước tiên hãy xem xét vấn đề đơn giản hơn: bổ sung.

Đầu tiên chúng ta làm một vấn đề quen thuộc, thêm vào 10 số cơ bản thông thường:

 17
+28

Bước đầu tiên sẽ là thêm 7 và 8. Nhưng kết quả này là 15, nhiều hơn một chữ số. Vì vậy, chúng tôi thực hiện 1:

(1)
 17
+28
= 5

Bây giờ chúng ta thêm 1, 1 và 2 lại với nhau:

 17
+28
=45

Vì vậy, từ điều này, chúng tôi nhận được các quy tắc sau:

  1. khi kết quả của phép cộng nhiều hơn một chữ số, chúng tôi sẽ giữ chữ số có nghĩa ít nhất và chuyển tiếp chữ số có ý nghĩa nhất

  2. nếu chúng ta có một chữ số được chuyển tiếp vào cột của mình, chúng ta sẽ thêm nó cùng với các số chúng ta thêm vào

Bây giờ là lúc để giải thích các quy tắc trên trong cơ sở 2 - đại số boolean.

Vì vậy, trong đại số boolean, cộng 0 và 1 với nhau = 1. Thêm 0 và 0 = 0. Và thêm 1 và 1 = 10 có nhiều hơn một chữ số để chúng ta tiến lên 1 về phía trước.

Từ đó chúng ta có thể xây dựng một bảng chân lý:

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

Từ đó, chúng ta có thể xây dựng hai mạch / phương trình boolean - một cho đầu ra của tổng và một cho đầu ra của carry. Cách ngây thơ nhất là chỉ đơn giản là liệt kê ra tất cả các đầu vào. Bất kỳ bảng chân lý nào, dù lớn và phức tạp đều có thể được trình bày lại theo hình thức này:

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

Đây là cơ bản tổng số các hình thức sản phẩm. Chúng tôi chỉ nhìn vào kết quả đầu ra là 1 và bỏ qua 0:

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

Hãy thay thế VÀ HOẶC và KHÔNG bằng các ký hiệu ngôn ngữ lập trình để dễ đọc hơn:

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

Về cơ bản, chúng tôi đã chuyển đổi bảng như vậy:

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

Điều này có thể được thực hiện trực tiếp như một mạch:

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

Tại thời điểm này, các độc giả quan sát sẽ nhận thấy rằng logic trên thực tế có thể được triển khai như một cổng duy nhất - một cổng XOR thuận tiện có hành vi theo yêu cầu của bảng chân lý của chúng tôi:

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

Nhưng nếu phần cứng của bạn không cung cấp cho bạn một cổng XOR, các bước ở trên là cách bạn tiến hành xác định và triển khai nó theo các cổng AND, OR và KHÔNG.

Cách bạn chuyển đổi cổng logic sang phần cứng thực tế phụ thuộc vào phần cứng bạn có. Chúng có thể được thực hiện bằng các cơ chế vật lý khác nhau miễn là cơ chế này cung cấp một số loại hành vi chuyển đổi. Các cổng logic đã được thực hiện với tất cả mọi thứ, từ tia nước hoặc luồng khí (chất lỏng) đến bộ chuyển đổi (thiết bị điện tử) đến viên bi rơi. Đó là một chủ đề lớn theo đúng nghĩa của nó vì vậy tôi sẽ chỉ đề cập đến nó và nói rằng có thể thực hiện các cổng logic như các thiết bị vật lý.

Bây giờ chúng tôi làm tương tự cho tín hiệu mang. Vì chỉ có một điều kiện trong đó tín hiệu mang là đúng, nên phương trình đơn giản là:

carry = a & b

Vì vậy, thực hiện rất đơn giản:

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

Kết hợp chúng lại với nhau, chúng ta sẽ có được cái gọi là nửa cộng:

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

Các phương trình cho mạch trên bằng cách này trông như thế này:

sum = a ^ b
carry = a & b

Bộ cộng một nửa là thiếu một cái gì đó. Chúng tôi đã thực hiện quy tắc đầu tiên - nếu kết quả nhiều hơn một chữ số so với chuyển tiếp, nhưng chúng tôi đã không thực hiện quy tắc thứ hai - nếu có một quy tắc cộng thêm cùng với các số.

Vì vậy, để thực hiện một bộ cộng đầy đủ, một mạch thêm có thể thêm các số có nhiều hơn một chữ số, chúng ta cần xác định một bảng chân lý:

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

Phương trình tổng là bây giờ:

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

Chúng ta có thể trải qua quá trình tương tự để xác định và đơn giản hóa phương trình và giải thích nó như một mạch, v.v. như chúng ta đã làm ở trên nhưng tôi nghĩ câu trả lời này đang trở nên quá dài.

Bây giờ bạn sẽ có một ý tưởng về cách logic kỹ thuật số được thiết kế. Có những thủ thuật khác mà tôi chưa đề cập như bản đồ Karnaugh (được sử dụng để đơn giản hóa các bảng chân lý) và các trình biên dịch logic như espresso (để bạn không phải tính các phương trình boolean bằng tay) nhưng cơ bản là những gì tôi đã đã nêu ở trên:

  1. Phân tích vấn đề cho đến khi bạn có thể làm việc ở mức một bit (chữ số).

  2. Xác định kết quả đầu ra mà bạn muốn bằng bảng chân lý.

  3. Chuyển đổi bảng thành phương trình boolean và đơn giản hóa phương trình.

  4. Giải thích phương trình như cổng logic.

  5. Chuyển đổi mạch logic của bạn sang các mạch phần cứng thực bằng cách thực hiện các cổng logic.

Đó là cách giải quyết các vấn đề cơ bản (hay đúng hơn là cấp độ thấp) - rất nhiều và rất nhiều bảng chân lý. Công việc sáng tạo thực sự nằm trong việc phá vỡ một nhiệm vụ phức tạp như giải mã MP3 thành cấp độ bit để bạn có thể làm việc với nó bằng các bảng chân lý.

Xin lỗi tôi không có thời gian để giải thích cách thực hiện phép nhân. Bạn có thể thử bẻ khóa nó bằng cách tìm ra các quy tắc về thời gian nhân lên sau đó diễn giải nó thành nhị phân sau đó thử chia nó thành các bảng chân lý. Hoặc bạn có thể đọc Wikipedia: http://en.wikipedia.org/wiki/Binary_multiplier


2

hướng dẫn số học cơ bản được thực hiện với hướng dẫn lắp ráp có hiệu quả cao.

Các hướng dẫn phức tạp hơn (hoặc trừu tượng) được thực hiện trong quá trình lắp ráp với các cơ chế lặp hoặc được xử lý trong lib std.

Khi bạn học toán ở trường đại học, bạn sẽ bắt đầu học những thứ như Lambda Tính và ký hiệu Big-O. Tất cả những thứ này, và nhiều thứ khác, được các lập trình viên sử dụng để đánh giá và tạo ra các thuật toán hiệu quả. Dù sao, những thứ cơ bản thường được hoàn thành ở cấp độ thấp như trong lắp ráp hoặc trong c với con trỏ.

Một giới thiệu tuyệt vời cho chủ đề này là "Mã" của Charles Petzold.


1
Hoặc bảng tra cứu. Nhanh hơn nhiều để tính toán trước các giá trị và tìm kiếm chúng. Ví dụ Sin / Cos / Tan (phân chia số nguyên mặc dù điều này được tính toán trước và được lưu trữ trong phần cứng).
Martin York

1

Nhận một cuốn sách như Nguyên tắc cơ bản về logic kỹ thuật số ... , mà tôi nghĩ vẫn còn khá chuẩn cho sinh viên Freshman / Sophomore EE, và tìm cách vượt qua nó (ed: nó tốn một khoản tiền nhỏ, vì vậy hãy tìm một phiên bản đã sử dụng hoặc trước nó). Điều đó sẽ đưa bạn qua các bộ cộng và số nhân, và cung cấp cho bạn đủ nền tảng để bắt đầu hiểu một số nguyên tắc đằng sau những gì phần cứng đang làm.

Câu trả lời của bạn, trong ngắn hạn, sẽ trở thành "bởi vì nó phù hợp với nhiều mảnh logic đơn giản hơn để gợi lên hành vi phức tạp này" thay vì "bởi vì nó".

Nếu bạn muốn cố gắng hiểu tất cả các nguyên tắc về cách các chương trình được biên dịch và chạy, hãy kết hợp với nó, để cuối cùng bạn có thể thấy mọi thứ gặp nhau ở giữa như thế nào.


1

Có rất nhiều câu trả lời tốt ở đây. Bạn cũng bắt đầu với ý tưởng đúng: các hoạt động phức tạp như phép nhân được xây dựng từ các hoạt động đơn giản hơn. Như bạn đã đoán, có nhiều cách nhân nhanh hơn mà không cần hướng dẫn nhân hơn là sử dụng một loạt các bổ sung. Bất kỳ phép nhân nào cũng có thể được thực hiện dưới dạng tổng của các phép nhân nhỏ hơn hoặc là sự kết hợp của các ca và phép cộng. Ví dụ:

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

Bộ phận cũng có thể được chia thành các hoạt động nhỏ hơn. XOR (^) là một hướng dẫn tích hợp trên mọi bộ xử lý mà tôi từng xem, nhưng ngay cả như vậy nó có thể được triển khai dưới dạng kết hợp giữa AND, OR và KHÔNG.

Tuy nhiên, tôi có cảm giác rằng các câu trả lời cụ thể sẽ ít thỏa mãn với bạn hơn là một ý tưởng chung về các loại hướng dẫn mà bộ xử lý cung cấp và cách các hướng dẫn đó có thể được kết hợp thành các hoạt động phức tạp hơn. Không có gì tốt hơn cho sự tò mò đó hơn là một ngôn ngữ lắp ráp lành mạnh. Đây là một giới thiệu rất dễ tiếp cận với ngôn ngữ lắp ráp MIPS.


1

Đây là cách bộ xử lý hiện đại có thể thực hiện phép nhân hai số nguyên 64 bit:

Bạn biết làm thế nào để nhân một tay dài. Để nhân hai số có 10 chữ số, bạn sẽ nhân một số có 10 chữ số cho mỗi trong số 10 chữ số của số kia, viết kết quả 11 chữ số này bên dưới số kia và thay đổi, sau đó thêm tất cả số.

Một bộ xử lý hiện đại thực hiện điều này với tất cả 64 x 64 bit. Tuy nhiên, phép nhân hai số bit đơn rất đơn giản: 1 x 1 = 1, tất cả các sản phẩm khác đều bằng không. Điều này được thực hiện với một logic và. Và không giống như sản phẩm thập phân, trong đó kết quả có thể là hai chữ số, sản phẩm nhị phân của các số bit đơn luôn là một bit.

Vì vậy, bây giờ bạn có 64 hàng 64 bit cần được thêm vào. Nhưng 64 bổ sung của số 64 bit là slooooooow. Vì vậy, bộ xử lý sử dụng bộ cộng 3/2 hoặc bộ cộng 7/3: Nếu bạn thêm 3 số bit đơn, kết quả có thể là 0, 1, 2 hoặc 3, khớp với hai bit. Nếu bạn thêm 7 số bit đơn, kết quả là một số từ 0 đến 7, có thể được biểu thị bằng 3 bit. IBM tuyên bố họ có thể tạo ra một bộ cộng 7/3 chỉ với 18 mạch nguyên thủy (tài liệu PowerPC), tôi cá là Intel và ARM cũng có thể làm điều này.

Bạn có 4096 bit, nhóm chúng thành khoảng 600 nhóm 7 bit ở cùng vị trí bit và sử dụng khoảng 600 bộ cộng 7/3 để giảm kết quả từ 4096 bit xuống dưới 2.000. Sau đó, bạn làm tương tự, và một lần nữa, cho đến khi bạn kết thúc với các cặp bit có thể được đưa vào một bộ cộng đầy đủ thông thường.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.