Mantissa Là Gì

  -  

Tôi có một chương trình đang chạy trên hai bộ xử lý, một trong số đó không có hỗ trợ dấu phẩy động. Vì vậy, tôi cần thực hiện các phép tính dấu phẩy động bằng cách sử dụng điểm cố định trong bộ xử lý đó. Với mục đích đó, tôi sẽ sử dụng một thư viện mô phỏng điểm nổi. 

Trước tiên tôi cần trích xuất các dấu hiệu, mantissas và số mũ của các số dấu phẩy động trên bộ xử lý có hỗ trợ dấu phẩy động. Vì vậy, câu hỏi của tôi là làm thế nào tôi có thể nhận được dấu, mantissa và số mũ của một số dấu phẩy động chính xác duy nhất.

Bạn đang xem: Mantissa là gì

Theo định dạng từ hình này, 

*
Đó là những gì tôi đã làm cho đến nay, nhưng ngoại trừ dấu hiệu, cả mantissa và số mũ đều không đúng. Tôi nghĩ rằng, tôi đang thiếu một cái gì đó.

void getSME( int& s, int& m, int& e, float number ){ unsigned int* ptr = (unsigned int*)&number; s = *ptr >> 31; e = *ptr & 0x7f800000; e >>= 23; m = *ptr & 0x007fffff;}
cfloating-pointemulation
35
28 thg 3, 2013MetallicPriest
Tôi nghĩ tốt hơn là sử dụng các công đoàn để thực hiện các diễn viên, nó là rõ ràng hơn.

#include typedef union { float f; struct { unsigned int mantisa : 23; unsigned int exponent : 8; unsigned int sign : 1; } parts;} float_cast;int main(void) { float_cast d1 = { .f = 0.15625 }; printf("sign = %x\n", d1.parts.sign); printf("exponent = %x\n", d1.parts.exponent); printf("mantisa = %x\n", d1.parts.mantisa);}Ví dụ dựa trên http://en.wikipedia.org/wiki/Single_precision


Tìm ra định dạng của các số dấu phẩy động được sử dụng trên CPU hỗ trợ trực tiếp điểm nổi và chia nó thành các phần đó. Định dạng phổ biến nhất là IEEE-754 .

Xem thêm: Outfit Là Gì ? Tìm Hiểu Về Thuật Ngữ “Outfit” Trong Thời Trang

Ngoài ra, bạn có thể có được những phần đó bằng cách sử dụng một vài chức năng đặc biệt (double frexp(double value, int *exp); và double ldexp(double x, int exp);) như trong câu trả lời này .

Một tùy chọn khác là sử dụng %a với printf().


Lời khuyên của tôi là hãy tuân thủ quy tắc 0 và không làm lại những thư viện tiêu chuẩn đã làm, nếu điều này là đủ. Nhìn vào math.h (cmath trong C++ tiêu chuẩn) và các hàm frexp, frexpf, frexpl, phá vỡ một giá trị dấu phẩy động (double, float hoặc long double) trong phần ý nghĩa và số mũ của nó. Để trích xuất dấu hiệu từ ý nghĩa và bạn có thể sử dụng Signbit, cũng như trong math.h/cmath hoặc copysign (chỉ C++ 11). Một số lựa chọn thay thế, với ngữ nghĩa khác nhau nhẹ hơn, là modf và ilogb/scalbn, có sẵn trong C++ 11; http://en.cppreference.com/w/cpp/numeric/math/logb so sánh chúng, nhưng tôi không tìm thấy trong tài liệu về cách tất cả các chức năng này hoạt động với +/- inf và NaNs. Cuối cùng, nếu bạn thực sự muốn sử dụng bitmasks (ví dụ: bạn rất cần biết các bit chính xác và chương trình của bạn có thể có các NaN khác nhau với các cách biểu diễn khác nhau và bạn không tin tưởng các chức năng trên) bằng cách sử dụng các macro trong float.h/cfloat.

Xem thêm: Đường Link Là Gì ? Ý Nghĩa Của Đường Link Trong Việc Làm Seo


Bạn đang &ing các bit sai. Tôi nghĩ bạn muốn:

s = *ptr >> 31;e = *ptr & 0x7f800000;e >>= 23;m = *ptr & 0x007fffff;Hãy nhớ rằng, khi bạn &, bạn sẽ loại bỏ các bit mà bạn không đặt. Vì vậy, trong trường hợp này, bạn muốn loại bỏ bit dấu khi bạn nhận được số mũ và bạn muốn loại bỏ bit dấu và số mũ khi bạn nhận được mantissa.

Lưu ý rằng các mặt nạ đến trực tiếp từ hình ảnh của bạn. Vì vậy, mặt nạ số mũ sẽ trông như sau:

0 11111111 00000000000000000000000

và mặt nạ mantissa sẽ trông như:

0 00000000 1111111111111111111111111


Trên các gói tiêu đề glibc của Linux cung cấp tiêu đề #include với các định nghĩa loại dấu phẩy động, ví dụ:

union ieee754_double { double d; /* This is the IEEE 754 double-precision format. */ struct {#if __BYTE_ORDER == __BIG_ENDIAN unsigned int negative:1; unsigned int exponent:11; /* Together these comprise the mantissa. */ unsigned int mantissa0:20; unsigned int mantissa1:32;#endif /* Big endian. */#if __BYTE_ORDER == __LITTLE_ENDIAN# if __FLOAT_Word_ORDER == __BIG_ENDIAN unsigned int mantissa0:20; unsigned int exponent:11; unsigned int negative:1; unsigned int mantissa1:32;# else /* Together these comprise the mantissa. */ unsigned int mantissa1:32; unsigned int mantissa0:20; unsigned int exponent:11; unsigned int negative:1;# endif#endif /* Little endian. */ } ieee; /* This format makes it easier to see if a NaN is a signalling NaN. */ struct {#if __BYTE_ORDER == __BIG_ENDIAN unsigned int negative:1; unsigned int exponent:11; unsigned int quiet_nan:1; /* Together these comprise the mantissa. */ unsigned int mantissa0:19; unsigned int mantissa1:32;#else# if __FLOAT_Word_ORDER == __BIG_ENDIAN unsigned int mantissa0:19; unsigned int quiet_nan:1; unsigned int exponent:11; unsigned int negative:1; unsigned int mantissa1:32;# else /* Together these comprise the mantissa. */ unsigned int mantissa1:32; unsigned int mantissa0:19; unsigned int quiet_nan:1; unsigned int exponent:11; unsigned int negative:1;# endif#endif } ieee_nan; };#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */
Đừng tạo các hàm làm nhiều việc.Đừng đeo mặt nạ sau đó thay đổi; thay ca rồi đắp mặt nạ.Đừng thay đổi giá trị một cách không cần thiết vì nó chậm, phá hủy bộ đệm và dễ bị lỗi.Đừng sử dụng số ma thuật./* NaNs, infinities, denormals unhandled *//* assumes sizeof(float) == 4 and uses ieee754 binary32 format *//* assumes two"s-complement machine *//* C99 */#include #define SIGN(f) (((f) > FLOAT_MANTISSA_WIDTH) & MASK(FLOAT_EXPONENT_WIDTH)) - FLOAT_BIAS;}/* of non-zero, normal floats only */int float_mantissa(float f) { return (int)(AS_U32(f) & MASK(FLOAT_MANTISSA_BITS)) | FLOAT_IMPLICIT_MANTISSA_BIT;}/* Hacker"s Delight book is your friend. */
Điều này hoạt động tốt cho double kiểu dữ liệu:

In Binary: 0 0b00000011101 0b1011100010000101101110010011001010111101000111111000In Decimal: 0 29 3246151636341240
Sự khác biệt giữa float và double là gì?

Hậu tố của "f" trên giá trị float?

Hàm C để chuyển đổi float sang mảng byte

Công cụ xác định chiều rộng Printf để duy trì độ chính xác của giá trị dấu phẩy động

Trích phần thập phân từ số dấu phẩy động trong C

Cách biểu thị số FLOAT trong bộ nhớ trong C

C chuyển đổi dấu phẩy động sang int

Có một chức năng để làm tròn một dấu phẩy trong C hoặc tôi cần phải tự viết?

Sử dụng float với sprintf () trong C nhúng

Ngoại lệ điểm nổi

Biên dịch một ứng dụng để sử dụng trong môi trường phóng xạ cao

"Tĩnh" có nghĩa là gì trong C?

Sự khác biệt giữa const int *, const int * const và int const * là gì?

Kiểu dữ liệu float và double trong Java

makefile: 4: *** thiếu dấu phân cách. Dừng lại

Sự khác biệt giữa một định nghĩa và một tuyên bố là gì?

Cái nào nhanh hơn: while (1) hay while (2)?

Có một công cụ chuyển đổi printf để in ở định dạng nhị phân?

MIN và MAX trong C

Chia chuỗi với các dấu phân cách trong C