Недавно обнаружил, что в C++ при умножении или делении нуля на отрицательное число, в ответ записывается не 0, а -0. Из-за этой особенности долгое время не мог сдать задачу. Решил проблему так:
printf("%llf", ans == 0 ? fabs(ans) : ans);
Существует ли более красивое решение?
А почему бы не сделать просто printf(“%llf”, fabs(ans)); ? Вообще такое происходит, потому что все операции с действительными числами выполняются с некоторой погрешностью, что значит что умножение и деление это не в чистом виде умножение и деление, поэтому и 0 может быть как 0+EPS так и 0-EPS.
Понял почему бы не сделать так. А можно ссылку на задачу, на которой так происходит, ибо по идее не должно быть ошибки.
-0 <> 0 — это Вы правильно подметили! Задача и тесты, вылавливающие неаакуратную работу с вещественными числами в этом направлении размещена здесь. Сразу отмечу, что все тесты корректны, ответы целочисленны, и, естественно, как вариант ответа число "-0" не содержат.
Эта Ваша задача решается с помощью перебора целочисленных делителей свободного члена.
Как вариант просто сдать — да, можно сдать перебором. :(
Но она же решается школьным математическим методом решения квадратного уравнения (собственно на это она и расчитана, а не на полный перебор), если акуратно работать с вещественными числами.
Неправильный ответ должен решателю напомнить, что в памяти компьютера все числа хранятся не в десятичной форме, а в двоичной, и поэтому важен порядок вычислений.
Я говорил не про полный перебор, а про перебор делителей свободного члена. Не знаю, как для Вас, а для меня это тоже школьный математический метод, был у нас на одном из дополнительных предметов физико-математического профиля ("Избранные вопросы математики").
Речь не идёт о специализированных классах, изучавших углубленно математику или программирование.
Тут речь должна начаться с того, откуда взята задача — это задача с ГИА (аналог ЕГЭ в Украине) и рассчитана на обычных школьников, которые сдают задачу не по предмету "Программирование" или "Углубленный курс математики", а учащиеся всех школ, выбравшие на ГИА предмет "Информатика", т.е. спец.знаний по математике или программированию не нужно, а понятие о делителях свободного члена для большинства из них, к глубокому сожалению, ещё больше непонятнее, чем полный перебор.
А понятие о двоичном представлении числа с плавающей точкой, ИМХО, еще непонятнее, чем понятие о делителях свободного члена.
UPD. Я неплохо помню про Ваше мнение о том, что наиболее правильное решение задачи — то, которое придумали Вы и именно Вы. Продолжать спор дальше у меня нет никакого желания.
Ответы сами по себе могут быть отрицательными.
Вообще-то ноль на самом деле может иметь знак: http://en.wikipedia.org/wiki/Signed_zero
Почему минусуют этот пост? Да, я ошибся малость, но это была не основная суть коммента, которая вроде как верна.
Такое происходит, потому что стандарт IEEE 754 поддерживает 2 нуля: +0 и -0, которые хоть и равны, выводятся по-разному (см. ссылку выше).
Пример:
Выведется -0, хотя умножение выполнено точно.
нет, минусуют именно потому что он ошибся, так как вот это мало кто знал, пока вы не сказали
Да нет там точного умножения. Число 0.0 это не чистый ноль, это может быть например 0.000000000000000000126418, то есть это очень маленькое число, близкое к 0 (обычно приближается к нулю с положительной стороны), поэтому и умножение его на отрицательное даёт очень маленькое отрицательное число, то есть -0, что на самом деле -0.0000000000000000293647 (то есть близкое к нулю слева).
Сколько знаков не выводил, после точки видел только нули.
А вообще зачем 0.0 делать не чистым нулём, когда есть чистый +0?
хочется вам верить, ну сколько знаков не вывел, ничего нет после запятой, кроме нулей
Если глянуть в устройство вещественного числа по стандарту IEEE-754, то там нет никаких причин, почему 0.0 и -1.0 не могут быть представлены абсолютно точно. В этом формате число разложено по целым степеням двойки (4, 2, 1, 1/2, 1/4 ...), именно поэтому не получится точно представить 1/3 или даже 0.1.
плюсану вас, пусть вам будет проще =)
Нет, просто коль так сильно минусуют, хочется знать за что. Может я ошибся в основной — второй части коммента.
А в задаче, что, посимвольный чекер? И, если не секрет, она не на е-олимпе?
Можно к ответу всегда прибавлять EPS.
Я в Петрозаводске перед выводом написал "x = x;", и у меня выводилось без минуса.
У меня так получилось только с GNU C++, но в MV C++ это не работает.
Кстати, на правах оффтопа на тему отрицательных нулей и С++. Мне что-то последнее время Code::Blocks часто стал выдавать такого рода картинку: Что бы это значило?
Вот как раз сегодня наткнулся, в вики была ссылка http://habrahabr.ru/post/112953/ Очень познавательно, советую.
в посте значится
printf(“%llf”, ans == 0 ? fabs(ans) : ans);
мне не нравится здесь== 0
для даблов, думаю лучше(fabs(ans) < eps) ? 0.0 : ans;