Thực sự không khác biệt gì so với bạn làm bằng bút chì và giấy. Được rồi một khác nhau chút
123400 - 5432 = 1.234*10^5 - 5.432*10^3
số lớn hơn chiếm ưu thế, chuyển mantissa số nhỏ hơn của tắt vào xô chút cho đến khi số mũ phù hợp
1.234*10^5 - 0.05432*10^5
sau đó thực hiện phép trừ với mantissas
1.234 - 0.05432 = 1.17968
1.17968 * 10^5
Sau đó chuẩn hóa (trong trường hợp này là)
Điều đó với 10 số cơ bản.
Trong IEEE phao, độ chính xác đơn
123400 = 0x1E208 = 0b11110001000001000
11110001000001000.000...
bình thường hóa mà chúng ta phải thay đổi vị trí thập phân 16 bậc lên vị trí bên trái để
1.1110001000001000 * 2^16
Số mũ được thiên vị vì vậy chúng tôi thêm 127-16 và nhận được 143 = 0x8F.Đó là một số dương vì vậy bit dấu là 0 chúng ta bắt đầu xây dựng số dấu phẩy IEEE hàng đầu 1 trước khi số thập phân được ngụ ý và không được sử dụng trong độ chính xác đơn, chúng ta loại bỏ nó và giữ nguyên phân số
dấu bit, mũ, mantissa
0 10001111 1110001000001000...
0100011111110001000001000...
0100 0111 1111 0001 0000 0100 0...
0x47F10400
và nếu bạn viết một chương trình để xem những gì một máy tính thứ 123.400 là bạn sẽ có được điều tương tự:
0x47F10400 123400.000000
vì vậy, chúng ta biết số mũ và mantissa cho là người đầu tiên toán hạng '
Bây giờ các toán hạng thứ hai
5432 = 0x1538 = 0b0001010100111000
Normalize, chuyển số thập phân 12 bit trái
1010100111000.000
1.010100111000000 * 2^12
Số mũ là biased thêm 127 và nhận được 139 = 0x8B = 0b10001011
Đặt nó tất cả cùng nhau
0 10001011 010100111000000
010001011010100111000000
0100 0101 1010 1001 1100 0000...
0x45A9C00
Và một chương trình/trình biên dịch máy tính cho cùng một số
0x45A9C000 5432.000000
Bây giờ để trả lời câu hỏi của bạn. Sử dụng các bộ phận cấu thành của số dấu chấm động, tôi đã khôi phục ngụ ý 1 ở đây vì chúng ta cần nó
0 10001111 111100010000010000000000 - 0 10001011 101010011100000000000000
Chúng ta phải xếp hàng chữ số thập phân của chúng tôi giống như trong trường lớp trước khi chúng tôi có thể trừ như vậy trong bối cảnh này, bạn phải thay đổi số mũ nhỏ hơn bên phải, đưa các bit ảo ra khỏi đầu cho đến khi số mũ khớp với nhau
0 10001111 111100010000010000000000 - 0 10001011 101010011100000000000000
0 10001111 111100010000010000000000 - 0 10001100 010101001110000000000000
0 10001111 111100010000010000000000 - 0 10001101 001010100111000000000000
0 10001111 111100010000010000000000 - 0 10001110 000101010011100000000000
0 10001111 111100010000010000000000 - 0 10001111 000010101001110000000000
Bây giờ chúng ta có thể trừ mantissas. Nếu các bit dấu khớp với nhau thì chúng ta sẽ trừ đi nếu chúng không khớp nhau thì chúng ta sẽ thêm vào. Chúng khớp với nhau sẽ là phép trừ.
máy tính thực hiện một phép trừ bằng cách sử dụng logic Ngoài ra, đảo ngược các nhà điều hành thứ hai trên đường vào bộ cộng và khẳng định thực hiện trong chút, như thế này:
1
111100010000010000000000
+ 111101010110001111111111
==========================
Và bây giờ giống như với giấy và bút chì cho phép thực hiện các thêm
1111000100000111111111111
111100010000010000000000
+ 111101010110001111111111
==========================
111001100110100000000000
hoặc làm điều đó với hex trên máy tính của bạn
111100010000010000000000 = 1111 0001 0000 0100 0000 0000 = 0xF10400
111101010110001111111111 = 1111 0101 0110 0011 1111 1111 = 0xF563FF
0xF10400 + 0xF563FF + 1 = 0x1E66800
1111001100110100000000000 =1 1110 0110 0110 1000 0000 0000 = 0x1E66800
Một chút về cách phần cứng hoạt động, vì đây thực sự là một phép trừ bằng cách sử dụng trình bổ sung, chúng tôi cũng đảo ngược bit thực hiện (hoặc trên một số máy tính mà chúng để nguyên). Vì vậy, mà thực hiện của 1 là một điều tốt, chúng tôi về cơ bản loại bỏ nó. Nếu nó được thực hiện một số không, chúng tôi sẽ cần nhiều công việc hơn. Chúng tôi không có một thực hiện để câu trả lời của chúng tôi thực sự là 0xE66800.
Rất nhanh chóng cho phép thấy rằng một cách khác, thay vì đảo ngược và thêm một phép chỉ cần sử dụng một máy tính
111100010000010000000000 - 000010101001110000000000 =
0xF10400 - 0x0A9C00 =
0xE66800
Bằng cách cố gắng hình dung nó tôi có lẽ đã làm cho nó tồi tệ hơn. Kết quả của phép trừ chú giải là 111001100110100000000000 (0xE66800), không có chuyển động nào trong bit quan trọng nhất mà chúng ta kết thúc bằng số bit 24 trong trường hợp này với msbit của 1. Không chuẩn hóa. Để bình thường hóa, bạn cần phải dịch chuyển mantissa sang trái hoặc sang phải cho đến khi 24 bit thẳng hàng với số 1 quan trọng nhất ở vị trí trái nhất đó, điều chỉnh số mũ cho mỗi lần dịch bit.
Bây giờ tước 1. chút tắt câu trả lời chúng tôi đặt các phần lại với nhau
0 10001111 11001100110100000000000
01000111111001100110100000000000
0100 0111 1110 0110 0110 1000 0000 0000
0x47E66800
Nếu bạn đã theo cùng bằng cách viết một chương trình để làm điều này, tôi đã làm là tốt. Chương trình này vi phạm tiêu chuẩn C bằng cách sử dụng một công đoàn một cách không đúng cách. Tôi đã đi với nó với trình biên dịch của tôi trên máy tính của tôi, không mong đợi nó để làm việc tất cả các thời gian.
#include <stdio.h>
union
{
float f;
unsigned int u;
} myun;
int main (void)
{
float a,b,c;
a=123400;
b= 5432;
c=a-b;
myun.f=a; printf("0x%08X %f\n",myun.u,myun.f);
myun.f=b; printf("0x%08X %f\n",myun.u,myun.f);
myun.f=c; printf("0x%08X %f\n",myun.u,myun.f);
return(0);
}
Và kết quả của chúng tôi phù hợp với đầu ra của chương trình trên, chúng tôi đã một 0x47E66800 làm việc đó bằng tay
0x47F10400 123400.000000
0x45A9C000 5432.000000
0x47E66800 117968.000000
Nếu bạn đang viết một chương trình để tổng hợp các toán dấu chấm động chương trình của bạn có thể thực hiện trừ, bạn không cần phải làm ngược và thêm một điều, hơn phức tạp nó như chúng ta đã thấy ở trên. Nếu bạn nhận được một kết quả tiêu cực mặc dù bạn cần phải chơi với bit dấu, đảo ngược kết quả của bạn, sau đó bình thường hóa.
Vì vậy:
1) trích xuất các phần, ký hiệu, số mũ, phần định trị.
2) Căn chữ số thập phân của bạn bằng cách hy sinh bit mantissa từ số với số mũ nhỏ nhất, chuyển mantissa rằng sang bên phải cho đến khi số mũ phù hợp
3) là một hoạt động trừ nếu các bit dấu hiệu đều giống nhau sau đó bạn thực hiện một trừ, nếu các bit dấu hiệu khác nhau bạn thực hiện thêm một mantissas.
4) nếu kết quả là một số không thì câu trả lời của bạn là một số không, mã hóa các giá trị IEEE cho không như kết quả, nếu không:
5) bình thường hóa số lượng, chuyển câu trả lời sang phải hoặc trái (Câu trả lời có thể là 25 bit từ cộng thêm/trừ 24 bit, cộng/trừ có thể có một sự thay đổi đáng kể để chuẩn hóa, hoặc là một hoặc nhiều bit sang trái) cho đến khi bạn có số 24 bit với số quan trọng nhất còn lại. 24 bit là cho phao chính xác đơn. Cách chính xác hơn để xác định bình thường hóa là dịch chuyển sang trái hoặc sang phải cho đến khi số này giống với 1.cái gì đó. nếu bạn đã có 0,001 bạn sẽ chuyển sang trái 3, nếu bạn có 11,10 bạn sẽ chuyển phải 1. một sự thay đổi bên trái làm tăng số mũ của bạn, một quyền thay đổi giảm nó. Không khác với khi chúng ta chuyển đổi từ số nguyên sang phao ở trên.
6) đối với độ chính xác đơn loại bỏ hàng đầu 1. từ phần định trị, nếu số mũ đã tràn thì bạn sẽ xây dựng một nan báo hiệu. Nếu các bit dấu hiệu khác nhau và bạn thực hiện thêm, thì bạn phải đối phó với việc tìm ra bit dấu kết quả. Nếu như trên tất cả mọi thứ tốt, bạn chỉ cần đặt bit dấu, số mũ và mantissa trong kết quả
Nhân và chia là khác nhau, bạn hỏi về thu nhỏ, vì vậy đó là tất cả tôi được bảo hiểm.
bản sao có thể có của [Thực hiện phép trừ dấu phẩy động] (http://stackoverflow.com/questions/591046/implementing-floating-point-subtraction) –
Tại sao bạn không trừ? Tại sao bận tâm làm hoạt động bổ sung của 2 mình? –
@Carl Thats cách duy nhất tôi biết làm thế nào để trừ trong nhị phân -.- ' –