Có cách tiêu chuẩn và / hoặc di động nào để biểu diễn giá trị âm nhỏ nhất (ví dụ: sử dụng âm vô cực) trong chương trình C (++) không?
DBL_MIN trong float.h là số dương nhỏ nhất .
Có cách tiêu chuẩn và / hoặc di động nào để biểu diễn giá trị âm nhỏ nhất (ví dụ: sử dụng âm vô cực) trong chương trình C (++) không?
DBL_MIN trong float.h là số dương nhỏ nhất .
Câu trả lời:
-DBL_MAX
trong ANSI C , được định nghĩa trong float.h.
-DBL_MAX
phải có khả năng biểu diễn chính xác, vì vậy nếu phần cứng FP không có khả năng đó, thì việc triển khai chỉ phải làm việc xung quanh nó. Xem mô hình dấu phẩy động trong 5.2.4.2.2 Đặc điểm của các kiểu dấu phẩy động <float.h> p2 của C99 (có thể đã được chuyển đi nơi khác kể từ đó).
DBL_MAX
chính xác là (1 - b ^ −p) b ^ e_max, có thể biểu diễn chính xác, giá trị hữu hạn âm nhất chính xác là - (1 - b ^ −p) b ^ e_max, và vì điều đó xảy ra chính xác -DBL_MAX
nên việc phủ định DBL_MAX
cũng không thể tạo ra bất kỳ lỗi làm tròn nào.
Các số dấu phẩy động (IEEE 754) là đối xứng, vì vậy nếu bạn có thể đại diện cho giá trị lớn nhất ( DBL_MAX
hoặc numeric_limits<double>::max()
), chỉ cần thêm một dấu trừ.
Và sau đó là cách tuyệt vời:
double f;
(*((long long*)&f))= ~(1LL<<52);
Trong C, sử dụng
#include <float.h>
const double lowest_double = -DBL_MAX;
Trong C ++ trước 11, sử dụng
#include <limits>
const double lowest_double = -std::numeric_limits<double>::max();
Trong C ++ 11 trở đi, sử dụng
#include <limits>
constexpr double lowest_double = std::numeric_limits<double>::lowest();
min()
chức năng có sẵn trước khi C ++ 11? Hay đó là một giá trị khác -max()
? en.cppreference.com/w/cpp/types/numeric_limits
min
giá trị dương nhỏ nhất về độ lớn và lowest
giá trị âm lớn nhất về độ lớn. Vâng, thật là khủng khiếp. Chào mừng đến với thế giới rực rỡ của thư viện chuẩn C ++ :-P
.
float.h
. limits.h
dành cho số nguyên
Thử đi:
-1 * numeric_limits<double>::max()
Tài liệu tham khảo: numeric_limits
Lớp này chuyên biệt cho từng kiểu cơ bản, với các thành viên của nó trả về hoặc đặt thành các giá trị khác nhau xác định các thuộc tính của kiểu đó trong nền tảng cụ thể mà nó biên dịch.
-numeric_limits<double>::max()
?
-1 * ...
để làm cho nó rõ ràng hơn một chút.
Bạn đang tìm kiếm giá trị vô hạn thực tế hoặc giá trị hữu hạn tối thiểu? Nếu trước đây, hãy sử dụng
-numeric_limits<double>::infinity()
chỉ hoạt động nếu
numeric_limits<double>::has_infinity
Nếu không, bạn nên sử dụng
numeric_limits<double>::lowest()
đã được giới thiệu trong C ++ 11.
Nếu lowest()
không có sẵn, bạn có thể quay lại
-numeric_limits<double>::max()
điều này có thể khác lowest()
về nguyên tắc, nhưng thường không khác trong thực tế.
-numeric_limits<double>::max()
ngay cả khi nó hoạt động trong thực tế cũng không hoàn toàn có thể di chuyển được trên lý thuyết.
Như từ C ++ 11, bạn có thể sử dụng numeric_limits<double>::lowest()
. Theo tiêu chuẩn, nó trả về chính xác những gì bạn đang tìm kiếm:
Một giá trị hữu hạn x sao cho không có giá trị hữu hạn nào khác y ở đâu
y < x
.
Có ý nghĩa cho tất cả các chuyên ngành trong đóis_bounded != false
.
Có rất nhiều câu trả lời cho -std::numeric_limits<double>::max()
.
May mắn thay, chúng sẽ hoạt động tốt trong hầu hết các trường hợp. Các lược đồ mã hóa dấu chấm động phân tách một số trong phần định trị và số mũ và hầu hết chúng (ví dụ như IEEE-754 phổ biến ) sử dụng một bit dấu riêng biệt, không thuộc về phần định trị. Điều này cho phép biến đổi dương lớn nhất thành âm nhỏ nhất chỉ bằng cách lật dấu:
Tiêu chuẩn không áp đặt bất kỳ tiêu chuẩn dấu phẩy động nào.
Tôi đồng ý rằng lập luận của tôi hơi mang tính lý thuyết, nhưng giả sử rằng một nhà sản xuất trình biên dịch chuyên nghiệp nào đó sẽ sử dụng một lược đồ mã hóa mang tính cách mạng với phần định trị được mã hóa trong một số biến thể của phần bổ sung của hai . Mã hóa bổ sung của hai không đối xứng. ví dụ đối với một char 8 bit có dấu, giá trị dương tối đa là 127, nhưng giá trị âm tối thiểu là -128. Vì vậy, chúng ta có thể tưởng tượng một số mã hóa dấu phẩy động hiển thị hành vi bất đối xứng tương tự.
Tôi không biết về bất kỳ lược đồ mã hóa nào như vậy, nhưng vấn đề là tiêu chuẩn không đảm bảo rằng việc lật dấu hiệu mang lại kết quả dự kiến . Vì vậy, câu trả lời phổ biến này (xin lỗi các bạn!) Không thể được coi là giải pháp tiêu chuẩn di động hoàn toàn! / * ít nhất là không nếu bạn không khẳng định điều đó numeric_limits<double>::is_iec559
là đúng * /
Câu hỏi ban đầu liên quan đến vô hạn. Vì vậy, tại sao không sử dụng
#define Infinity ((double)(42 / 0.0))
theo định nghĩa của IEEE? Bạn có thể phủ nhận điều đó tất nhiên.
numeric_limits<double>::has_infinity && ! numeric_limits<double>::traps
Có cách tiêu chuẩn và / hoặc di động nào để biểu diễn giá trị âm nhỏ nhất (ví dụ: sử dụng âm vô cực) trong chương trình C (++) không?
C cách tiếp cận.
Nhiều triển khai hỗ trợ +/- infinities, vì vậy double
giá trị âm nhất là -INFINITY
.
#include <math.h>
double most_negative = -INFINITY;
Có một cách tiêu chuẩn và / hoặc di động ....?
Bây giờ chúng ta cũng cần xem xét các trường hợp khác:
Đơn giản -DBL_MAX
thôi.
Tôi mong đợi trong trường hợp này, OP sẽ thích hơn -DBL_MAX
.
DBL_MAX
.Đây là một trường hợp bất thường, có khả năng nằm ngoài mối quan tâm của OP. Khi double
được mã hóa dưới dạng một cặp dấu phẩy động để đạt được phạm vi / tuế sai mong muốn, (xem kép kép ) tồn tại giá trị bình thường tối đa double
và có lẽ là giá trị bình thường lớn hơn . Tôi đã thấy cuộc tranh luận nếu DBL_MAX
nên tham khảo điều bình thường lớn nhất , điều nhất của cả hai.
May mắn thay, cách tiếp cận được ghép nối này thường bao gồm-vô cùng, vì vậy giá trị âm nhất vẫn còn -INFINITY
.
Để có thêm tính di động, mã có thể đi xuống tuyến đường
// HUGE_VAL is designed to be infinity or DBL_MAX (when infinites are not implemented)
// .. yet is problematic with unsigned infinity.
double most_negative1 = -HUGE_VAL;
// Fairly portable, unless system does not understand "INF"
double most_negative2 = strtod("-INF", (char **) NULL);
// Pragmatic
double most_negative3 = strtod("-1.0e999999999", (char **) NULL);
// Somewhat time-consuming
double most_negative4 = pow(-DBL_MAX, 0xFFFF /* odd value */);
// My suggestion
double most_negative5 = (-DBL_MAX)*DBL_MAX;
Nếu bạn chưa bật ngoại lệ float (mà bạn không nên imho), bạn chỉ cần nói:
double neg_inf = -1/0.0;
Điều này mang lại âm vô cùng. Nếu bạn cần một phao, bạn có thể truyền kết quả
float neg_inf = (float)-1/0.0;
hoặc sử dụng số học chính xác đơn
float neg_inf = -1.0f/0.0f;
Kết quả luôn giống nhau, có chính xác một đại diện của âm vô cực ở cả độ chính xác đơn và kép, và chúng chuyển đổi cho nhau như bạn mong đợi.
-INFINITY
neg_inf
được khởi tạo thành một giá trị không đổi . Trình biên dịch sẽ đảm nhận việc tính toán inf
giá trị. Và khi bạn sử dụng nó dưới dạng null-value để tính toán giá trị tối đa, lần lặp đầu tiên thường sẽ ghi đè nó bằng một giá trị lớn hơn. Tức là hiệu suất hầu như không có vấn đề gì. Và OP hỏi cụ thể về "ví dụ: sử dụng âm vô cực", và -inf
thực sự là câu trả lời chính xác duy nhất cho điều này. Bạn đã phản đối một câu trả lời đúng và hữu ích.