У меня вопрос о модуле. Операция modulo находит остальную часть деления одного числа на другое. Я ожидал, что результат 0.5% 0.1 = 0. Но когда я запускаю это на PHP или .net, я получаю 0,1.
Код в php, который я запускал, был:
var_dump(fmod(0.5, 0.1));
В .net я испробовал следующее:
Console.WriteLine(0.5%0.1);
Я также попробовал онлайн-калькулятор http://www.calculatorpro.com/modulo-calculator/ .
Все эти 3 метода дали мне 0,1 в качестве ответа.
Но когда я печатаю это в google, я получаю результат, который я ожидал http://www.google.nl/search?source=ig&hl=nl&q=0.5%20mod%200.1&meta= .
Является ли это ошибкой в .net / php или Google знает правильный ответ? Может ли кто-нибудь объяснить, почему возникают эти различия?
Число, которое вы получаете на PHP или C # или C ++ или Python или что-то еще, когда вы запрашиваете 0,1, – это число с плавающей запятой с двойной точностью, что означает, что это конечная «десятичная» – с 53 значащими битами, включая первые 1-битные – – в базе 2. На самом деле то, что вы получите, является ближайшим точно представимым числом до 0,1, что, я думаю, составляет ровно 0,1000000000000000055511151231257827021181583404541015625.
С другой стороны, 0.5 является конечным «бицималом»; ценность, которую вы получите, когда вы попросите об этом, будет равна 0,5.
Поэтому 0,5 всего лишь немного меньше, чем в 5 раз «0,1», поэтому «0.5 mod 0.1» на самом деле дает вам что-то немного меньше 0,1. На самом деле, я думаю, что это точно 0.09999999999999997779553950749686919152736663818359375.
Теперь, когда вы задаете PHP или C # или что-то еще, чтобы отобразить этот номер, он отобразит некоторое количество цифр. Вы действительно не хотите, чтобы это отображало всю ужасную вещь. (Подумайте: предположим, вы просто попросите отобразить 0,1, вам нужно чудовищное чудовище, или вы хотите «0,1»? Думали так.) И число на самом деле очень близко к 0,1; если вы не запросите более 15 цифр точности, то правильная вещь для отображения – всего лишь «0,1».
Наблюдайте (это Python, с которым мне было удобно):
>>> for n in range(10,20): print (("%%.%dg"%n)%(0.5%0.1)) 0.1 0.1 0.1 0.1 0.1 0.1 0.09999999999999998 0.099999999999999978 0.0999999999999999778 0.0999999999999999778
Итак: не ошибка; на самом деле вопрос о плавающей запятой не подходит для «точных вычислений» (иногда это уместно, иногда нет, дело в том, чтобы понять, что он делает и что вам нужно); может или не может указывать на то, что вы бы лучше использовали целые числа, в зависимости от вашей реальной потребности.
Чтобы узнать больше об этом, чем вы, вероятно, хотите узнать, взгляните на «Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой» .
Что касается того, почему калькулятор Google дает ожидаемый ответ 0, я не знаю. Возможно, они используют десятичную арифметику – реальные номера базы-10 – чтобы свести к минимуму неожиданные сюрпризы. (Это, как правило, намного медленнее, чем использование встроенной с плавающей запятой, но у Google есть много доступных процессоров, и я делаю ставку только на небольшую часть работы, которую их машины обработки изображений имеют какое-либо отношение к калькулятору.)
Нет, это не ошибка, так как операция modulo может быть определена и с номерами с плавающей запятой. В вашем PHP-коде вы явно используете fmod()
вместо %
и в .NET оператор %
определен для каждого числового типа ( контрольная ссылка )
0 – целочисленный ответ, а 0,1 – результат правого поплавка
дополнительно посмотреть на wolframalpha: http://www.wolframalpha.com/input/?i=0.5+mod+0.1
Если вы хотите оценить 0.5%0.1
, вы, вероятно, могли бы (и должны) использовать целочисленную арифметику. Например, если вы вычисляете что-то, связанное с валютой, обычно лучше хранить количество центов как целое число, чем хранить сумму в виде числа с плавающей запятой.