ฉันจะเริ่มต้น float เป็นค่าสูงสุด / นาทีได้อย่างไร


101

ฉันจะฮาร์ดโค้ดค่าสูงสุดหรือต่ำสุดสัมบูรณ์สำหรับทศนิยมหรือสองเท่าได้อย่างไร ฉันต้องการค้นหาค่าสูงสุด / นาทีของอาร์เรย์โดยเพียงแค่วนซ้ำและจับค่าที่ใหญ่ที่สุด

นอกจากนี้ยังมีค่าอนันต์บวกและลบสำหรับการลอยฉันควรใช้สิ่งเหล่านี้แทนหรือไม่? ถ้าเป็นเช่นนั้นฉันจะระบุว่าในรหัสของฉันได้อย่างไร

คำตอบ:


154

คุณสามารถใช้std::numeric_limitsซึ่งกำหนดไว้<limits>เพื่อค้นหาค่าต่ำสุดหรือสูงสุดของประเภท (ตราบเท่าที่มีความเชี่ยวชาญเฉพาะสำหรับประเภท) คุณยังสามารถใช้เพื่อดึงข้อมูลอินฟินิตี้ (และวางไว้-ด้านหน้าสำหรับอินฟินิตี้เชิงลบ)

#include <limits>

//...

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

ตามที่ระบุไว้ในความคิดเห็นmin()จะส่งกลับค่าบวกต่ำสุดที่เป็นไปได้ กล่าวอีกนัยหนึ่งคือค่าบวกที่ใกล้เคียงที่สุดกับ 0 ที่สามารถแสดงได้ ค่าต่ำสุดที่เป็นไปได้คือค่าลบของค่าสูงสุดที่เป็นไปได้

แน่นอนว่ามีstd::max_elementฟังก์ชันและ min_element (กำหนดไว้ใน<algorithm>) ซึ่งอาจเป็นทางเลือกที่ดีกว่าสำหรับการค้นหาค่าที่ใหญ่ที่สุดหรือน้อยที่สุดในอาร์เรย์


ฉันจะใช้สิ่งนี้ได้อย่างไร? ฉันต้องใส่อะไรบ้าง? ฉันไม่คิดว่าฉันเคยใช้อะไรแบบนี้มาก่อน
ถ่ายเมื่อ

อืม ... ฟังก์ชั่นองค์ประกอบสูงสุดนั้นจะมีประโยชน์มาก ... นี่คือสิ่งที่เกิดขึ้นเมื่อคุณเรียนรู้การเข้ารหัสด้วยตัวคุณเองและไม่เป็นทางการ คุณจบลงด้วยการสร้างล้อใหม่กว่า 50 ครั้ง นี่ก็เหมือนกับครั้งสุดท้ายที่ฉันเรียนรู้เกี่ยวกับ ceil () ขอบคุณ.
ถ่ายเมื่อ

18
@Yacoby คุณอาจต้องการชี้แจงว่า numeric_limits <float> :: min () ไม่ได้หมายถึงค่าลบส่วนใหญ่หมายถึงค่าบวกที่น้อยที่สุด
MSN

13
@killogre: เพิ่ม C ++ 11 numeric_limits<T>::lowest()ซึ่งส่งคืนค่าต่ำสุด (ลบ) ที่เป็นไปได้สำหรับประเภทที่จะแก้ปัญหานี้
Cornstalks

3
std::numeric_limits<float>::min()ไม่ได้ให้ค่าบวกที่เล็กที่สุดที่สามารถเป็นตัวแทนของ; จะให้เลขทศนิยมตำแหน่งเดียวที่มีความแม่นยำต่ำที่สุดตามปกติ นอกจากนี้ยังมีตัวเลขย่อยระหว่างศูนย์กับตัวเลขนี้ โดยเฉพาะอย่างยิ่งstd::numeric_limits<float>::min()จะช่วยให้แต่มีขนาดเล็กที่สุดลอยต่ำกว่าปกติซึ่งแสดงเป็น1.17549e-38 nextafterf(0.0f, 1.0f) == 1.4013e-45f
nibot

47

คุณสามารถใช้-FLT_MAX(หรือ-DBL_MAX) สำหรับจำนวนลบขนาดสูงสุดและFLT_MAX(หรือDBL_MAX) สำหรับค่าบวก ค่านี้ให้ช่วงของค่า float (หรือ double) ที่เป็นไปได้

คุณอาจไม่ต้องการใช้FLT_MIN; มันสอดคล้องกับจำนวนบวกที่มีขนาดเล็กที่สุดที่สามารถแทนค่าได้ด้วยค่าลอยไม่ใช่ค่าที่เป็นลบมากที่สุดที่แทนค่าได้ด้วยลูกลอย

FLT_MINและFLT_MAXสอดคล้องกับและstd::numeric_limits<float>::min()std::numeric_limits<float>::max()


ฉันคิดว่าฉันจะใช้เวอร์ชันนี้จริงมันง่ายกว่าที่จะจำและสร้างฉากให้ฉันมากขึ้น จำนวนเต็มฉันสามารถเริ่มต้นโดยใช้เลขฐานสิบหก แม้ว่าคำตอบที่ดีที่สุดยังคงอยู่เพราะคำตอบนี้ยังแนะนำให้ฉันรู้จักกับฟังก์ชันใหม่ ๆ ที่มีประโยชน์อย่างยิ่ง
ถ่ายเมื่อ

2
"[ FLT_MIN] สอดคล้องกับจำนวนที่เล็กที่สุดขนาดบวกที่สามารถแสดงกับลอย" - นี้ไม่เป็นความจริง มันเป็นตัวเลขปกติที่เล็กที่สุด นอกจากนี้ยังมีตัวเลขย่อยปกติ
nibot

คุณต้องการFLT_TRUE_MINลอยที่เล็กที่สุดเท่าที่จะเป็นไปได้ซึ่งสอดคล้องกับstd::numeric_limits<float>::denorm_min()
Chris Dodd

17

ไม่จำเป็นต้องเริ่มต้นให้เล็กที่สุด / ใหญ่ที่สุดเท่าที่จะเป็นไปได้เพื่อค้นหาสิ่งที่เล็กที่สุด / ใหญ่ที่สุดในอาร์เรย์:

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

หรือหากคุณทำมากกว่าหนึ่งครั้ง:

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

ข้อเสียของการให้โค้ดตัวอย่าง - ฉันเห็นว่ามีคนอื่นแนะนำแนวคิดเดียวกันนี้แล้ว

โปรดทราบว่าแม้ว่ามาตรฐานจะมี min_element และ max_element แต่การใช้สิ่งเหล่านี้จะต้องมีการสแกนข้อมูลสองครั้งซึ่งอาจเป็นปัญหาได้หากอาร์เรย์มีขนาดใหญ่เลย มาตรฐานล่าสุดได้แก้ไขปัญหานี้โดยการเพิ่ม a std::minmax_elementซึ่งทำเช่นเดียวกับfind_extremaข้างต้น (ค้นหาทั้งองค์ประกอบต่ำสุดและสูงสุดในคอลเลกชันในรอบเดียว)

แก้ไข: แก้ไขปัญหาในการค้นหาค่าที่ไม่ใช่ศูนย์ที่เล็กที่สุดในอาร์เรย์ที่ไม่ได้ลงนาม: สังเกตว่าค่าที่ไม่ได้ลงชื่อ "ล้อมรอบ" เมื่อถึงจุดสูงสุด ในการหาค่าที่ไม่ใช่ศูนย์ที่เล็กที่สุดเราสามารถลบค่าหนึ่งออกจากแต่ละค่าเพื่อเปรียบเทียบได้ ค่าศูนย์ใด ๆ จะ "ล้อมรอบ" เป็นค่าที่มากที่สุดเท่าที่จะเป็นไปได้สำหรับประเภทนั้น แต่ความสัมพันธ์ระหว่างค่าอื่น ๆ จะยังคงอยู่ หลังจากที่เราทำเสร็จแล้วเราจะเพิ่มกลับเข้าไปในค่าที่พบ

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

โปรดทราบว่าสิ่งนี้ยังคงใช้องค์ประกอบแรกสำหรับค่าเริ่มต้น แต่เรายังไม่ต้องการรหัส "กรณีพิเศษ" ใด ๆ เนื่องจากจะรวมเป็นค่าที่มากที่สุดเท่าที่จะเป็นไปได้ค่าใด ๆ ที่ไม่ใช่ศูนย์จะเปรียบเทียบว่ามีค่าน้อยกว่า ผลลัพธ์จะเป็นค่าที่ไม่ใช่ศูนย์ที่เล็กที่สุดหรือ 0 ก็ต่อเมื่อเวกเตอร์ไม่มีค่าที่ไม่ใช่ศูนย์


แต่คุณได้รับ +1 จากฉัน!
Dan Diplo

1
ฉันเริ่มต้นเป็นนาทีสูงสุดเพราะบางครั้งฉันต้องการค่าที่ไม่ใช่ศูนย์น้อยที่สุด (เช่นในกรณีจำนวนเต็มไม่ได้ลงชื่อข้อมูลของฉันมักจะมีศูนย์ที่ไม่น่าสนใจจำนวนมาก) ดูเหมือนว่าจะสมเหตุสมผลสำหรับฉันที่จะเริ่มต้นมากกว่าที่จะทำการตรวจสอบเพิ่มเติมล่วงหน้าเพื่อให้แน่ใจว่าองค์ประกอบแรกไม่เป็นศูนย์
ถ่ายเมื่อ

@ Faken: แม้ว่าคุณจะสามารถกำหนดฟังก์ชันเปรียบเทียบที่ถือว่าศูนย์เป็นค่าที่มากที่สุดได้ดังนั้นคุณยังสามารถใช้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 จะเพิ่ม minmax_element เพื่อแก้ไขปัญหาที่คุณกล่าวถึง (แต่ถ้าอย่างนั้นก็จะไม่สนใจเลขศูนย์ ... )
UncleBens

1
จะเกิดอะไรขึ้นหากองค์ประกอบแรกไม่พร้อมใช้งานในขณะเริ่มต้น สิ่งนี้เกิดขึ้นมากมายในการประมวลผลออนไลน์ (เช่นเดียวกับการเพิ่ม :: ตัวสะสม)
killogre

5

ในการค้นหาอาร์เรย์ขั้นต่ำด้วยตนเองคุณไม่จำเป็นต้องทราบค่าต่ำสุดของ float:

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

และรหัสที่คล้ายกันสำหรับค่าสูงสุด


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.