bagaimana cara saya menginisialisasi float ke nilai maksimal / minnya?

100

Bagaimana saya membuat kode keras nilai maksimum atau minimum absolut untuk float atau double? Saya ingin mencari maks / menit dari sebuah array hanya dengan mengulang dan menangkap yang terbesar.

Ada juga positif dan negatif tak terhingga untuk pelampung, haruskah saya menggunakan itu? Jika demikian, bagaimana cara menunjukkannya dalam kode saya?

Salah
sumber

Jawaban:

152

Anda dapat menggunakan std::numeric_limitsyang ditentukan dalam <limits>untuk menemukan nilai minimum atau maksimum dari tipe (selama spesialisasi ada untuk tipe). Anda juga dapat menggunakannya untuk mengambil tak terhingga (dan meletakkan -di depan untuk tak terhingga negatif).

#include <limits>

//...

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

Seperti yang dicatat di komentar, min()mengembalikan nilai positif serendah mungkin. Dengan kata lain nilai positif yang paling mendekati 0 yang dapat direpresentasikan. Nilai serendah mungkin adalah negatif dari nilai semaksimal mungkin.

Tentu saja ada fungsi std::max_elementdan min_element (ditentukan dalam <algorithm>) yang mungkin merupakan pilihan yang lebih baik untuk menemukan nilai terbesar atau terkecil dalam sebuah array.

Yacoby
sumber
Bagaimana tepatnya saya menggunakan ini? Apa yang perlu saya sertakan? Saya tidak berpikir saya pernah menggunakan sesuatu seperti ini sebelumnya.
Dipalsukan
Hmm ... fungsi elemen maks itu akan sangat berguna ... inilah yang terjadi ketika Anda belajar pengkodean sendiri dan tidak secara formal. Anda akhirnya menemukan kembali roda tersebut 50 kali lipat. Ini seperti terakhir kali saya belajar tentang ceil (). Terima kasih.
Dipalsukan
18
@Yacoby, Anda mungkin ingin menjelaskan bahwa numeric_limits <float> :: min () tidak berarti nilai paling negatif, itu berarti positif terkecil.
MSN
13
@killogre: C ++ 11 ditambahkan numeric_limits<T>::lowest(), yang mengembalikan nilai terendah (negatif) yang mungkin untuk tipe untuk memecahkan masalah ini.
Cornstalks
3
std::numeric_limits<float>::min()tidak tidak memberikan nilai positif terkecil yang dapat diwakili; ini memberikan angka floating point presisi tunggal normal terkecil . Ada juga angka di bawah normal antara nol dan angka ini. Secara khusus, std::numeric_limits<float>::min()memberi 1.17549e-38tetapi float subnormal terkecil yang dapat diwakili adalah nextafterf(0.0f, 1.0f) == 1.4013e-45f.
nibot
45

Anda dapat menggunakan -FLT_MAX(atau -DBL_MAX) untuk bilangan negatif magnitudo maksimum dan FLT_MAX(atau DBL_MAX) untuk positif. Ini memberi Anda kisaran kemungkinan nilai float (atau double).

Anda mungkin tidak ingin menggunakan FLT_MIN; itu sesuai dengan bilangan positif magnitudo terkecil yang dapat diwakili dengan float, bukan nilai paling negatif yang dapat diwakili dengan float.

FLT_MINdan FLT_MAXsesuai dengan std::numeric_limits<float>::min()dan std::numeric_limits<float>::max().

MSN
sumber
Saya rasa saya akan menggunakan versi ini sebenarnya, lebih sederhana untuk diingat dan membuat lebih banyak adegan bagi saya. Bilangan bulat saya bisa menginisialisasi menggunakan heksadesimal. Padahal, jawaban terbaik tetap ada karena jawabannya juga memperkenalkan saya pada beberapa fungsi baru yang sangat berguna.
Dipalsukan
2
"[ FLT_MIN] sesuai dengan bilangan positif magnitudo terkecil yang dapat direpresentasikan dengan float" - Ini tidak benar . Itu angka normal terkecil . Ada juga angka di bawah normal.
nibot
Anda ingin FLT_TRUE_MINpelampung terkecil yang sebenarnya, yang sesuai denganstd::numeric_limits<float>::denorm_min()
Chris Dodd
17

Tidak ada kebutuhan nyata untuk menginisialisasi ke terkecil / terbesar untuk menemukan terkecil / terbesar dalam array:

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];
}

Atau, jika Anda melakukannya lebih dari sekali:

#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;
}

Kerugian dari memberikan kode sampel - Saya melihat orang lain telah menyarankan ide yang sama.

Perhatikan bahwa sementara standar memiliki min_element dan max_element, menggunakan ini akan memerlukan pemindaian melalui data dua kali, yang bisa menjadi masalah jika lariknya besar sama sekali. Standar terbaru telah mengatasi hal ini dengan menambahkan a std::minmax_element, yang melakukan hal yang sama seperti di find_extremaatas (temukan elemen minimum dan maksimum dalam koleksi dalam sekali jalan).

Sunting: Mengatasi masalah menemukan nilai bukan nol terkecil dalam larik unsigned: amati bahwa nilai unsigned "membungkus" ketika mencapai nilai ekstrem. Untuk mencari nilai bukan nol terkecil, kita dapat mengurangi satu dari masing-masing untuk perbandingan. Setiap nilai nol akan "membungkus" ke nilai terbesar yang mungkin untuk jenis tersebut, tetapi hubungan antara nilai lain akan dipertahankan. Setelah kami selesai, kami jelas menambahkan satu kembali ke nilai yang kami temukan.

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;
}

Perhatikan bahwa ini masih menggunakan elemen pertama untuk nilai awal, tetapi kami masih tidak memerlukan kode "kasus khusus" - karena kode tersebut akan menghasilkan nilai terbesar yang mungkin, nilai bukan nol apa pun akan dibandingkan sebagai lebih kecil. Hasilnya akan menjadi nilai bukan nol terkecil, atau 0 jika dan hanya jika vektor tidak berisi nilai bukan nol.

Jerry Coffin
sumber
Tapi Anda mendapatkan +1 untuk itu dari saya!
Dan Diplo
1
Saya memulai ke max menit karena terkadang saya menginginkan nilai terkecil bukan nol (dalam kasus integer unsigned misalnya, data saya cenderung memiliki banyak angka nol yang tidak menarik). Sepertinya masuk akal bagi saya untuk menginisialisasi daripada melakukan pemeriksaan tambahan untuk memastikan elemen pertama tidak nol.
Dipalsukan
@ Salah: Meski begitu Anda dapat menentukan fungsi perbandingan yang memperlakukan nol sebagai nilai terbesar, jadi Anda masih dapat menggunakan 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
2
@Jerry: C ++ 0x akan menambahkan minmax_element untuk mengatasi masalah yang Anda sebutkan. (Tapi kemudian tidak mungkin mengabaikan nol ...)
UncleBens
1
Bagaimana jika elemen pertama tidak tersedia pada saat inisialisasi? Ini banyak terjadi dalam pemrosesan online (seperti dalam boost :: akumulator)
killogre
5

Untuk menemukan nilai minimum array secara manual, Anda tidak perlu mengetahui nilai minimum float:

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

Dan kode serupa untuk nilai maksimum.

Tagihan
sumber
4

Bolehkah saya menyarankan agar Anda menginisialisasi variabel "maks dan min sejauh ini" bukan hingga tak terbatas, tetapi ke angka pertama dalam larik?

Thomas Padron-McCarthy
sumber