2012-01-07 54 views
7

Làm cách nào để trừ số IEEE 754?Làm cách nào để trừ số IEEE 754?

Ví dụ: 0,546875 - 32,875 ...

-> 0,546875 là 0 01.111.110 10001100000000000000000 trong IEEE-754

-> -32,875 là 1 10.000.111 01000101111000000000000 trong IEEE-754

Vậy làm cách nào để thực hiện phép trừ? Tôi biết tôi phải làm cả hai số mũ bằng nhau nhưng tôi phải làm gì sau đó? 2'Thực hiện của -32.875 mantissa và thêm với 0,546875 mantissa?

+0

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) –

+1

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? –

+0

@Carl Thats cách duy nhất tôi biết làm thế nào để trừ trong nhị phân -.- ' –

Trả lời

21

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.

+0

Câu trả lời này đi vào nhiều khía cạnh, nhưng bỏ qua các tác động của làm tròn. Ngay cả khi không làm tròn, Bước 2) đã được đơn giản hóa. Phép trừ có thể hủy bit hàng đầu sao cho MSBit chuyển ra ngoài không được hy sinh, nhưng vẫn giữ lại. Ví dụ 4 bit: Nghĩ đến 1.000 - 0.1111 -> 0,0001, không có 0,001 – chux

Các vấn đề liên quan