2009-04-29 13 views
12

W numeric_limits cechy ma być ogólny sposób pozyskania typu różne infomation, aby móc robić takie rzeczy jakJak obejść niespójną definicję numeric_limits <T> :: min()?

template<typename T> 
T min(const std::vector<T>& vect) 
{ 
    T val = std::numeric_limits<T>::min(); 

    for(int i=0 ; i<vect.size() ; i++) 
     val = max(T, vect[i]); 

    return val; 
} 

Problem polega na tym, że (przynajmniej przy użyciu MS Visual Studio 2008) numerycznych _ limity <int> :: min() zwraca najmniejszą liczbę ujemną, a numeryczne _ ogranicza < podwójne:: min() zwraca najmniejszy pozytywny numer!

Ktoś zna racjonalność tego projektu? Czy istnieje lepszy (zalecany?) Sposób korzystania z limitów numerycznych _? W moim konkretnej funkcji powyżej, mogę oczywiście zainicjować T VECT [0], ale to nie jest odpowiedź szukam ..

Zobacz również (floating-point-specyficzna) dyskusja here

+0

W twoim przykładzie występują dwa błędy. 1. Funkcję należy nazwać max(), ponieważ oblicza ona maksymalny element. 2. wiersz "val = max (T, vect [i])" powinien być "val = max (val, vect [i])". – TonJ

Odpowiedz

1

Rozwiązaniem byłoby

double val = -std::numeric_limits<double>::max(); 

oczywiście, to nie wyjaśnia dziwne zachowanie numerics_limits :: min(), które mogą być wynikiem faktu, że istnieją różne min/max granice dla liczb całkowitych (min = -2^n, max = 2^n-1), ale nie dla podwójnych.

+0

Czy std :: numeric_limits :: max() == -std :: numeric_limits :: min()? –

+0

Nie sądzę - tak jak napisałem, myślę, że min = -2^31, max = 2^31-1 dla 32-bitowych typów danych na przykład. Jest to największa ujemna/dodatnia wartość int - gcc potwierdza to: "min: -2147483648, max: 2147483647" – schnaader

+0

To jest punkt, który próbuję wprowadzić. Twój kod jest NIEPRAWIDŁOWY. –

9

Możesz użyć bibliotek Boost. Biblioteka Numeric Conversions udostępnia klasę o nazwie bounds, która może być używana konsekwentnie.

Zobacz dokumentację here.

4

Zachowanie min() nie jest takie dziwne, zwraca FLT_MIN, DBL_MIN lub INT_MIN (lub ich odpowiednie wartości), w zależności od typu, w którym specjalizuje się. Więc twoje pytanie powinno być, dlaczego FLT_MIN i DBL_MIN są zdefiniowane inaczej niż INT_MIN.

Niestety, nie znam odpowiedzi na to drugie pytanie.

Podejrzewam, że tak zdefiniowano w celach praktycznych. W przypadku liczb całkowitych zazwyczaj dotyczy to przepełnienia/niedopełnienia, w którym wartość minimalna i maksymalna stają się przedmiotem zainteresowania.

W przypadku liczb zmiennoprzecinkowych istnieje inny rodzaj niedomiaru, ponieważ obliczenie może spowodować, że wartość jest większa od zera, ale mniejsza niż najmniejsza reprezentowalna liczba dziesiętna dla tego typu zmiennoprzecinkowego. Wiedząc, że najmniejsza reprezentowalna wartość zmiennoprzecinkowa pozwala na obejście problemu. Zobacz także artykuł z Wikipedii na numerach subnormal/denormal.

1

Można podać definicję najmniejszej wartości pustego wektora. Jeśli wektor jest pusty, nie ma najmniejszego elementu.

wolą używać std::min_element zamiast:

int main() 
{ 
    std::vector<int> v; 
    std::generate_n(std::back_inserter(v), 1000, std::rand); 

    std::vector<int>::iterator it = std::min_element(v.begin(), v.end()); 
    if (it == v.end()) 
    { 
     std::cout << "There is no smallest element" << std::endl; 
    } 
    else 
    { 
     std::cout << "The smallest element is " << *it << std::endl; 
    } 
} 
1

Nie jestem pewien, ale to uzasadnienie jest oczekiwane zachowanie. Cóż, w tym sensie tak to opisuje Josuttis (i prawdopodobnie norma)!

min() "Miniumum skończona wartość (minimalna znormalizowana wartość zmiennoprzecinkową typów z denormalizacji)".

Jak najlepiej sprawdzić, czy typ jest nie liczbą całkowitą (numeric_limits<>::is_integer) i ma Denormalizacja (numeric_limits<>::has_denorm) min() powróci najmniejszą wartość reprezentowalna przez tego typu. W przeciwnym razie zwróci najmniejszą wartość o wartości - która może być ujemna.

Aby uzyskać bardziej spójny interfejs, należy przejrzeć bibliotekę Boost numeric/conversion. W szczególności: bounds traits class. Oto urywek:

cout << "lowest float:" << boost::numeric::bounds<float>::lowest(); 
cout << "lowest int: " << boost::numeric::bounds<int>::lowest(); 

Możesz również znaleźć przydatne narzędzie boost::integer library. Wprowadza część obsługi liczb całkowitych C99 (np. int_least16_t) do C++ i może pomóc wybrać najlepiej dopasowany typ do konkretnych potrzeb. Przykład:

boost::uint_t<20>::fast fastest20bits; // fastest unsigned integer that 
             // can hold at least 20 bits. 
boost::int_max_value_t<100000>::least // smallest integer that can store 
             // the value 100000. 

I często, że kiedy potrzebuję jednego z boost :: numerycznej/konwersji lub boost :: całkowitą I oboje potrzebujemy.

1

numeric_limits<int>::min zwrócił liczbę ujemną najniższa, wszystkie typy pływających numer punktu, zwraca liczbę najmniejszy pozytywny, gdy próbowałem go z Sun CC & g ++.

Sądzę, że dzieje się tak dlatego, że "najmniejszy" i "minimum" oznaczają różne rzeczy z liczbami zmiennoprzecinkowymi. To trochę dziwne.

Zarówno Sun CC ig ++ ten sam wynik:

skrócie: min: max: 32767 -32768

Int: min: -2147483648 max: 2147483647

unsigned int: min 0 maks: 4294967295

długi: min: -2147483648 maks: 2147483647

pływak: min: 1.17549e-38 mA X: 3.40282e + 38

podwójna: min: 2.22507e-308 max: 1.79769e + 308

długości dwukrotnie: min: 3.3621e-4932 max: 1.18973e + 4932

unsigned skrócie: min: 0 max: 65535

unsigned int: min: 0 max: 4294967295

unsigned long: min: 0 maks: 429496729

template<typename T> 
void showMinMax() 
{ 
    cout << "min: " << numeric_limits<T>::min() << endl; 
    cout << "max: " << numeric_limits<T>::max() << endl; 
    cout << endl; 
} 

int main() 
{ 
cout << "short:"; 
showMinMax<short>() 
...etc...etc.. 
+1

Dziwne, numeric_limits :: min zwraca tu bardzo małą dodatnią liczbę (g ++ 3.4. 5). Być może zależy to od wersji/OS/wdrożenia – schnaader

5

To jest stary wątek, ale jest zaktualizowana odpowiedź:

C++ 11 dodano funkcję lowest() do std::numeric_limits (See here)

Możesz teraz zadzwonić pod numer std::numeric_limits<double>::lowest(), aby uzyskać najniższą reprezentowalną wartość ujemną.

Powiązane problemy