làm cách nào để khởi tạo một float thành giá trị max / min của nó?


100

Làm cách nào để tạo mã cố định giá trị tối đa hoặc tối thiểu tuyệt đối cho float hoặc double? Tôi muốn tìm kiếm tối đa / tối thiểu của một mảng bằng cách chỉ cần lặp lại và bắt giá trị lớn nhất.

Ngoài ra còn có vô cực dương và âm cho phao, tôi có nên sử dụng chúng thay thế không? Nếu vậy, làm cách nào để biểu thị điều đó trong mã của tôi?

Câu trả lời:


151

Bạn có thể sử dụng giá trị std::numeric_limitsđược xác định trong <limits>để tìm giá trị tối thiểu hoặc lớn nhất của các loại (Miễn là tồn tại một chuyên môn hóa cho loại). Bạn cũng có thể sử dụng nó để truy xuất vô cực (và đặt -trước cho vô cực âm).

#include <limits>

//...

std::numeric_limits<float>::max();
std::numeric_limits<float>::min();
std::numeric_limits<float>::infinity();

Như đã lưu ý trong các nhận xét, min()trả về giá trị dương thấp nhất có thể. Nói cách khác, giá trị dương gần nhất với 0 có thể được biểu diễn. Giá trị thấp nhất có thể là âm của giá trị lớn nhất có thể.

Tất nhiên, có các hàm std::max_elementvà min_element (được định nghĩa trong <algorithm>) có thể là lựa chọn tốt hơn để tìm giá trị lớn nhất hoặc nhỏ nhất trong một mảng.


Làm thế nào để tôi sử dụng nó chính xác? Tôi cần bao gồm những gì? Tôi không nghĩ rằng tôi đã sử dụng một cái gì đó như thế này trước đây.
Faken

Hmm ... hàm phần tử tối đa đó sẽ rất hữu ích ... đây là những gì sẽ xảy ra khi bạn tự học mã hóa chứ không phải chính thức. Bạn sẽ sáng tạo lại bánh xe hơn 50 lần. Đây cũng giống như lần cuối cùng tôi học về ceil (). Cảm ơn bạn.
Faken

18
@Yacoby, bạn có thể muốn làm rõ rằng numeric_limits <float> :: min () không có nghĩa là giá trị âm nhất, nó có nghĩa là giá trị dương nhỏ nhất.
MSN

13
@killogre: Đã thêm C ++ 11 numeric_limits<T>::lowest(), trả về giá trị (âm) thấp nhất có thể cho kiểu giải quyết vấn đề này.
Cornstalks

3
std::numeric_limits<float>::min()không không cung cấp cho các giá trị dương nhỏ nhất có thể được đại diện; nó cung cấp số dấu phẩy động chính xác đơn thông thường nhỏ nhất . Cũng có những con số bất thường giữa số 0 và số này. Đặc biệt, std::numeric_limits<float>::min()cho 1.17549e-38nhưng số float phụ có thể biểu diễn nhỏ nhất là nextafterf(0.0f, 1.0f) == 1.4013e-45f.
nibot

45

Bạn có thể sử dụng -FLT_MAX(hoặc -DBL_MAX) cho số âm có độ lớn lớn nhất và FLT_MAX(hoặc DBL_MAX) cho số dương. Điều này cung cấp cho bạn phạm vi giá trị float (hoặc gấp đôi) có thể có.

Bạn có thể không muốn sử dụng FLT_MIN; nó tương ứng với số dương có độ lớn nhỏ nhất có thể được biểu diễn bằng số float, không phải giá trị âm nhất có thể biểu diễn bằng số float.

FLT_MINFLT_MAXtương ứng với std::numeric_limits<float>::min()std::numeric_limits<float>::max().


Tôi nghĩ tôi sẽ sử dụng phiên bản này thực sự, nó đơn giản hơn để nhớ và tạo nhiều cảnh hơn cho tôi. Số nguyên mà tôi có thể khởi tạo bằng hệ thập lục phân. Mặc dù vậy, câu trả lời tốt nhất vẫn ở lại vì câu trả lời cũng đã giới thiệu cho tôi một số chức năng mới cực kỳ hữu ích.
Faken

2
"[ FLT_MIN] tương ứng với số dương có độ lớn nhỏ nhất có thể được biểu diễn bằng dấu phẩy" - Điều này không đúng . Đó là số bình thường nhỏ nhất . Cũng có những con số siêu thường.
nibot

Bạn muốn FLT_TRUE_MINcho phao nhỏ nhất có thể thực tế, tương ứng vớistd::numeric_limits<float>::denorm_min()
Chris Dodd

17

Thực sự không cần thiết phải khởi tạo thành nhỏ nhất / lớn nhất có thể để tìm giá trị nhỏ nhất / lớn nhất trong mảng:

double largest = smallest = array[0];
for (int i=1; i<array_size; i++) {
    if (array[i] < smallest)
        smallest = array[i];
    if (array[i] > largest0
        largest= array[i];
}

Hoặc, nếu bạn đang làm điều đó nhiều lần:

#include <utility>

template <class iter>
std::pair<typename iter::value_type, typename iter::value_type> find_extrema(iter begin, iter end) {
    std::pair<typename iter::value_type, typename iter::value_type> ret;
    ret.first = ret.second = *begin;
    while (++begin != end) {
        if (*begin < ret.first)
           ret.first = *begin;
        if (*begin > ret.second)
           ret.second = *begin;
   }
   return ret;
}

Điểm bất lợi của việc cung cấp mã mẫu - Tôi thấy những người khác đã đề xuất ý tưởng tương tự.

Lưu ý rằng mặc dù tiêu chuẩn có min_element và max_element, việc sử dụng chúng sẽ yêu cầu quét qua dữ liệu hai lần, điều này có thể là một vấn đề nếu mảng lớn. Các tiêu chuẩn gần đây đã giải quyết vấn đề này bằng cách thêm a std::minmax_element, tương tự như find_extremaở trên (tìm cả phần tử tối thiểu và tối đa trong một tập hợp trong một lần chuyển).

Chỉnh sửa: Giải quyết vấn đề tìm giá trị khác 0 nhỏ nhất trong một mảng không dấu: quan sát rằng các giá trị không dấu "quấn quanh" khi chúng đạt đến cực trị. Để tìm giá trị khác 0 nhỏ nhất, chúng ta có thể trừ một giá trị cho mỗi giá trị để so sánh. Mọi giá trị 0 sẽ "quấn quanh" giá trị lớn nhất có thể cho kiểu, nhưng mối quan hệ giữa các giá trị khác sẽ được giữ lại. Sau khi hoàn thành, chúng tôi rõ ràng là thêm một trở lại giá trị mà chúng tôi đã tìm thấy.

unsigned int min_nonzero(std::vector<unsigned int> const &values) { 
    if (vector.size() == 0)
        return 0;
    unsigned int temp = values[0]-1;
    for (int i=1; i<values.size(); i++)
        if (values[i]-1 < temp)
            temp = values[i]-1;
    return temp+1;
}

Lưu ý rằng điều này vẫn sử dụng phần tử đầu tiên cho giá trị ban đầu, nhưng chúng tôi vẫn không cần bất kỳ mã "trường hợp đặc biệt" nào - vì điều đó sẽ bao quanh giá trị lớn nhất có thể, mọi giá trị khác 0 sẽ được so sánh là nhỏ hơn. Kết quả sẽ là giá trị khác không nhỏ nhất hoặc 0 nếu và chỉ khi vectơ không chứa giá trị khác 0.


Nhưng bạn nhận được +1 cho nó từ tôi!
Dan Diplo

1
Tôi nhập vào tối đa phút vì đôi khi tôi muốn giá trị khác 0 nhỏ nhất (ví dụ: trong trường hợp số nguyên không dấu, dữ liệu của tôi có xu hướng có nhiều số 0 không thú vị). Đối với tôi, có vẻ hợp lý khi khởi tạo nó hơn là tạo sẵn các kiểm tra bổ sung để đảm bảo phần tử đầu tiên không phải là số không.
Faken

@Faken: Ngay cả khi đó, bạn có thể xác định một hàm so sánh coi số 0 là giá trị lớn nhất có thể, vì vậy bạn vẫn có thể sử dụng std::min_element:bool less_ignoring_zero(unsigned a, unsigned b) { if (a == 0) return false; if (b == 0) return true; return a < b; }
UncleBens 21/04/10

2
@Jerry: C ++ 0x sẽ thêm minmax_element để giải quyết vấn đề bạn đề cập. (Nhưng sau đó sẽ không thể bỏ qua các số không ...)
UncleBens

1
Điều gì sẽ xảy ra nếu phần tử đầu tiên không có sẵn tại thời điểm khởi tạo? Điều này xảy ra rất nhiều trong xử lý trực tuyến (như trong boost :: ắc)
killogre

5

Để tìm giá trị tối thiểu của một mảng theo cách thủ công, bạn không cần biết giá trị nhỏ nhất của float:

float myFloats[];
...
float minimum = myFloats[0];
for (int i = 0; i < myFloatsSize; ++i)
{
  if (myFloats[i] < minimum)
  {
    minimum = myFloats[i];
  }
}

Và mã tương tự cho giá trị lớn nhất.


4

Tôi có thể đề nghị bạn khởi tạo các biến "tối đa và tối thiểu cho đến nay" của bạn không phải là vô cùng, mà là số đầu tiên trong mả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.