Меня смущает, почему мы заботимся о разных представлениях для положительного и отрицательного нуля.
Я смутно припоминаю чтение утверждений, что наличие отрицательного нулевого представления чрезвычайно важно в программировании, которое включает в себя комплексные числа. У меня никогда не было возможности написать код, включающий комплексные числа, поэтому я немного озадачен тем, почему это так.
Статья Википедии о концепции не особенно полезна; это только делает смутные заявления о нулевом знаке, делающем некоторые математические операции проще с плавающей запятой, если я правильно понимаю. В этом ответе перечислено несколько функций, которые ведут себя по-разному, и, возможно, что-то может быть выведено из примеров, если вы знакомы с тем, как их можно использовать. (Хотя конкретный пример сложных квадратных корней выглядит неверно, поскольку эти два числа математически эквивалентны, если только у меня нет недопонимания.) Но я не смог найти четкого утверждения о том типе неприятностей, с которыми вы бы столкнулись, если бы его там не было. Чем больше математических ресурсов я смог найти, так это тем, что не существует различий между ними с математической точки зрения, и статья в Википедии, похоже, предполагает, что это редко можно увидеть вне вычислений, помимо описания ограничений.
Так почему отрицательный ноль ценен в вычислительной технике? Я уверен, что просто что-то упустил.
источник
sqrt(-1+0i) = i
иsqrt(-1-0i) = -i
, хотя, я думаю, хотя и с правильным синтаксисом для некоторого языка программирования. Я буду редактировать, чтобы быть более понятным.Ответы:
Вы должны иметь в виду, что в арифметике FPU, 0 не обязательно должен означать ровно ноль, но также и значение слишком мало, чтобы быть представленным с использованием данного типа данных, например
a слишком мал, чтобы быть правильно представленным с плавающей точкой (32 бита), поэтому он «округляется» до -0.
Теперь предположим, что наше вычисление продолжается:
Поскольку a float, это приведет к -infinity, что довольно далеко от правильного ответа -1000000000000000000.0
Теперь давайте вычислим b, если нет -0 (поэтому a округляется до +0):
Результат снова неверен из-за округления, но теперь он «более неправильный» - не только численно, но, что более важно, из-за другого знака (результат вычисления + бесконечность, правильный результат -1000000000000000000.0).
Вы все еще можете сказать, что это не имеет значения, так как оба не правы. Важно то, что существует множество числовых приложений, где наиболее важным результатом вычислений является знак - например, при принятии решения, поворачивать ли влево или вправо на перекрестке, используя какой-либо алгоритм машинного обучения, вы можете интерпретировать положительное значение => поворот влево, отрицательное значение => повернуть направо, фактическая «величина» значения - это просто «коэффициент достоверности».
источник
+inf
и-inf
в нормальной работе, прослушиваются.+inf
и-inf
. Если ваша программа вызывает переполнение с плавающей запятой, это ошибка, и то, что происходит потом, не так интересно, imho. Мы все еще пропускаем практические примеры, в которых полезен -0.Во-первых, как вы создаете -0? Есть два способа: (1) выполнить операцию с плавающей запятой, где математический результат отрицателен, но настолько близок к нулю, что он округляется до нуля, а не до ненулевого числа. Этот расчет даст -0. (b) Некоторые операции с участием нулей: умножьте положительный ноль на отрицательное число, или разделите положительный ноль на отрицательное число, или отрицательный положительный ноль.
Наличие отрицательного нуля немного упрощает умножение и деление, знак x * y или x / y всегда является знаком x, исключающим или знаком y. Без отрицательного нуля потребуется дополнительная проверка, чтобы заменить -0 на +0.
Есть несколько очень редких ситуаций, когда это полезно. Вы можете проверить, является ли результат умножения или деления математически большим или меньшим нуля, даже если имеется недостаточное значение (если вы знаете, что результат не является математическим нулем). Я не помню, чтобы когда-либо писал код, где это имеет значение.
Оптимизация компиляторов ненависти -0. Например, вы не можете заменить x + 0.0 на x, потому что результат не должен быть x, если x равен -0.0. Вы не можете заменить x * 0.0 на 0.0, потому что результат должен быть -0.0, если x <0 или x равен -0.0.
источник
-5
и5
вfmod()
. Это довольно раздражает для моего случая использования.C # Double, который соответствует IEEE 754
печатает:
на самом деле, чтобы объяснить немного ...
Это означает что-то намного ближе к d =
The Limit of x as x approaches 0-
илиThe Limit of x as x approaches 0 from the negatives
.Чтобы ответить на комментарий Филиппа ...
В основном, отрицательный ноль означает недостаток.
Там очень мало практического использования для отрицательного нуля, если таковые имеются ...
например, этот код (снова C #):
дает такой результат:
Чтобы объяснить неформально, все специальные значения, которые может иметь IEEE 754 (положительная бесконечность, отрицательная бесконечность, NAN, -0.0), не имеют смысла в практическом смысле. Они не могут представлять какую-либо физическую ценность или любое значение, которое имеет смысл в вычислениях «реального мира». В основном они имеют в виду следующее:
sqrt(-7)
, или у него нет ограничения, как0/0
или какPositiveInfinity/PositiveInfinity
источник
Вопрос о том, как это относится к вычислениям комплексных чисел, действительно становится основой того, почему и +0, и -0 существуют в плавающей точке. Если вы вообще изучаете комплексный анализ, вы быстро обнаружите, что непрерывные функции от комплекса к комплексу обычно не могут рассматриваться как «однозначные», если не принять «вежливую беллетристику», в которой выходы образуют так называемую «поверхность Римана». Например, комплексный логарифм назначает каждому входу бесконечно много выходов; Когда вы «соединяете их», чтобы сформировать непрерывный выходной сигнал, вы получаете все реальные части, образующие «бесконечный штопор» вокруг источника. Непрерывная кривая, которая пересекает действительную ось «вниз от положительно-мнимой стороны» и другую кривую, которая «оборачивается вокруг полюса» и пересекает действительную ось »
Теперь примените это к числовой программе, которая вычисляет, используя сложные числа с плавающей точкой. Действие, предпринимаемое после данного расчета, может сильно отличаться в зависимости от того, на каком «листе» программа в данный момент «включена», а знак последнего вычисленного результата, вероятно, говорит вам, на каком «листе». Теперь предположим, что результат был нулевым? Помните, что здесь «ноль» действительно означает «слишком маленький, чтобы правильно представлять». Но если вычисление может обеспечить сохранение знака (т. Е. Запомнить, какой «лист»), когда результат равен нулю, тогда код может проверить знак и выполнить правильное действие даже в этой ситуации.
источник
Причина проще, чем обычно
Конечно, есть много хаков, которые выглядят действительно хорошо, и они полезны (например, округление до
-0.0
или,+0.0
но предположим, что у нас есть представление со знаком int со знаком минус / плюс в начале (я знаю, что это разрешается двоичным кодом U2). в целых числах обычно, но предполагают менее сложное представление double):Что делать, если есть отрицательное число?
Ладно, это так просто. Итак, давайте представим 0:
Это тоже хорошо. Но как насчет
1 000
? Это должен быть запрещенный номер? Лучше нетИтак, давайте предположим, что есть два типа нуля:
Что ж, это упростит наши расчеты и, к счастью, даст некоторые дополнительные возможности. Таким образом,
+0
и-0
исходят только из проблем двоичного представления.источник