2013-02-23 2 views
0

Я работаю над проектом и заканчиваю его. Мне нужно сделать некоторое сравнение с double, float ... проблема заключается в том, когда я сравниваю два двойных, которые являются соответственно самым большим значением для двойной и самое большое значение для двойной + 1, то сравнение не в состоянии ... я сделатьПочему мое сравнение между двойным сбоем C++

if (std::max(d_max + 1.1, (d_max)) == d_max) 
    std::cout << "bad" << std::endl; 

ответ функции МАХ d_max и «плохо» отображается ... кто-нибудь имеющий идея или решение, чтобы получить хорошую точность с моим сравнением? я проверил на google, но я узнал больше объяснений, чем реальное решение моей проблемы ... большое спасибо!

+6

Непонятно, что вы ожидаете отсюда. Если 'd_max' является максимальным значением для' double', вы не получите ничего выше. –

+0

Максимум ... <вставить цитату Inigo Montoya здесь> –

+0

Невозможно сравнить наивысшее значение двойного с другим значением без типа? – bottus

ответ

7

Все объекты в C++ имеют тип. Тип d_max - double. Тип d_max + 1.1 по-прежнему двойной. Если значение d_max является максимальным значением для double, то d_max + 1.1 не является представимым, и будет использоваться самое близкое представляемое значение, которое равно d_max (однако, если вы добавляете значительно большее значение, самое близкое представляемое значение считается положительной бесконечностью). Таким образом, ваш std::max вызов эквивалентен:

std::max(d_max, d_max) 

Чтобы продемонстрировать:

double d_max = std::numeric_limits<double>::max(); 
bool b = (d_max == (d_max + 1.1)); 
std::cout << std::boolalpha << b << std::endl; 

Это дает true как выход.


В ответ на ваш комментарий, я предполагаю, что вы делаете что-то вроде этого:

double d_max = std::numeric_limits<double>::max(); 
long double ld = d_max + 1; 
std::cout << (d_max == ld) << std::endl; 

И странно вы обнаружите, что, по-видимому d_max и ld равны. Зачем? Ну d_max - double. Когда вы делаете d_max + 1, результатом операции является также double - значение d_max + 1 не может быть представлено в double, хотя, как описано выше, так что выбрано самое близкое представляемое значение (d_max). Затем это значение присваивается ld.

Обратите внимание, что это вряд ли можно устранить, просто убедившись, что оператор приводит к long double (возможно, с d_max + 1.0L). При таких огромных количествах (около 10^308 с представлением IEEE 754) добавление 1 не приведет вас к следующему представляемому значению в long double. С моей реализации, я должен добавить 10 (который 1 следуют 289 нулями) фактически приводит к изменению значения:

double d_max = std::numeric_limits<double>::max(); 
long double ld = d_max + 1E289L; 
std::cout << (d_max == ld) << std::endl; 

Кроме того, нет никакой гарантии, что long double имеет большую точность, чем double. Единственная гарантия заключается в том, что она не имеет меньше точность.

+0

Я понимаю, что вы имеете в виду, но даже если я выполняю сравнение без функции max, и я сравниваю double с длинным двойным, которые являются havin соответственно для значения: max значение двойное и максимальное значение double + 1, я получаю ту же ошибку, что и раньше ... вот чего я не понимаю. если я не ошибаюсь, длинный двойник больше, чем двойной, не так ли? – bottus

+0

@bottus См. Мое редактирование. –

+0

@bottus - не предполагайте, что 'long double' больше, чем' double'. Проверь это. Используйте 'std :: numeric_limits :: max()'. –

1

Давайте сделаем вид, что двойники представлены в виде десятичных чисел с плавающей запятой, научной нотации.Тогда d_max будет что-то вроде

9.999999999999999999 ⋅ 10⁹⁹ 

Теперь давайте добавим 1.1 к этому:

9.999999999999999999 ⋅ 10⁹⁹ + 1.1 
= 999999999999999999900000000...000 + 1.1 
= 999999999999999999900000000...001.1 

круглых, что до 20, или даже 40 значащих цифр (которые вы должны как те виды, даже длинных двойного , имеют только ограниченную информационную емкость), и вы получите ...? ну, d_max еще раз.


Обратите внимание, что то же самое относится и к вычитанию, а также, так

int main() { 
    long double d_max = std::numeric_limits<double>::max(); 
    if(d_max == d_max - 1.1) 
    std::cout << " d_max  = " << d_max 
      << "\n== d_max - 1.1 = " << d_max + 1.1 << std::endl; 
    return 0; 
} 

выходы

d_max  = 1.79769e+308 
== d_max - 1.1 = 1.79769e+308 

то это на самом деле не имеет ничего общего с d_max является наибольшим значением в наличии, но с ним быть намного больше, чем вы добавляете к нему.

+0

хорошо, я хорошо понимаю, что вы объяснили;) Цель того, что я делаю, - это управлять потоком и переполнением в моей программе. мне нужно выполнить некоторую операцию, например *,/... ... Самая большая операция, которую я могу сделать, - это максимальное значение двойного * максимального значения double. Хорошо. но я хочу управлять переполнением для назначения. я имею в виду, если я сделаю небольшой тест, например двойной тест = 1000000000000000; моя программа не должна разрушаться, и я действительно не знаю, как это сделать ... когда я нашел пределы, я думаю, что этого будет достаточно, но, похоже, этого не будет. знаете ли вы, возможно ли это? Спасибо – bottus

+0

Я не понимаю, что именно вы пытаетесь сделать. – leftaroundabout

+0

Я пытаюсь поймать, когда есть возможность получить переполнение или нижнее течение. мой проект состоит в том, чтобы выполнять некоторую операцию между разными типами. когда вы пытаетесь присвоить значение типу непосредственно в вашей программе, ваш компилятор не позволяет вам это делать. но я делаю это с конфигурацией файла, такой как float (2.324) double (5.15154) mul (для умножения), можно поставить смешное значение в файл, и компилятор не увидит его, тогда мне нужно проверить присваивая, если есть underfor или overflow или нет;) – bottus

Смежные вопросы