Когда я программировал на C ++ несколько дней назад, я допустил эту ошибку (что у меня есть история создания этого!). В одной части моего кода у меня было 1/6, и я ожидал, что это будет 0,16666666666, что не так. Как вы все знаете, результат 0 - C, C ++, Java, Python, все ведут себя одинаково.
Я публикую это на своей странице в Facebook, и сейчас идет дискуссия о том, существует ли язык программирования, который 1/6
ведет себя так же, как и 1.0/6.0
.
>> 1 / 6
->== 0.166666666666667
1/6
фактически 1/6 (дробный тип), который по принуждениюDouble
равен 1.66666 ...Ответы:
Все забыли Паскаль?
1/6
доходность0.1666666...
(с любой точностью поддерживается).1 div 6
доходность0
Можно утверждать, является ли правило C ошибкой. Почти все арифметические операторы Си, в которых операнды имеют одинаковый тип, дают результат того же типа. Есть что-то, что нужно сказать для последовательности.
Кроме того, поскольку C в первую очередь нацелен на код системного уровня, большинство программ на C вообще не использует плавающую точку. Одно время, случайное добавление кода с плавающей точкой в программу, которая иначе не нуждалась в этом, могло быть серьезной проблемой. Это, вероятно, все еще имеет место для небольших встроенных систем, которые, опять же, являются основной целью для C.
В большинстве программ на C усечение целочисленного деления, вероятно, как раз то, что вам нужно.
Если
1 / 6
получен результат с плавающей точкой в C, то:double
может показаться естественным выбором, но вы могли бы предпочесть дополнительную точностьlong double
)C мог бы предоставить отдельные операторы для двух видов деления, но второй пункт выше все равно будет применяться: какой из трех типов с плавающей точкой будет использоваться для результата? И поскольку достаточно просто получить деление с плавающей запятой, если вам это нужно (используйте константу с плавающей запятой для одного или обоих операндов или приведите один или оба операнда к типу с плавающей запятой), очевидно, что Я считаю это важным.
В версии руководства C на 1974 год (это за 4 года до публикации первого издания K & R) Ричи даже не упоминает о возможной путанице:
который говорит, что если оба операнда имеют тип
int
илиchar
, результат имеет типint
.Да, это является источником путаницы для некоторых программистов на C, особенно начинающих, но C не известен тем, что он очень новичок.
источник
1.666666...
, что явно не так. Мое извинительное оправдание в том, что напечатанная мною программа тестирования на Паскале1.6666666666666667E-0001
На самом деле это поведение было изменено в Python 3, и теперь оно ведет себя так, как вы ожидаете (
//
теперь используется для целочисленного деления).источник
/
всегда создает значение с плавающей запятой, аdiv
для целочисленного деления используется отдельный оператор ( ).Из выдающихся языков JavaScript. 1,0 / 6,0 = 1/6 = 0,16666666666666666.
Я не вижу в этом ничего удивительного. Как правило, если язык различает целочисленные и числовые типы с плавающей запятой, разделение двух целых чисел приведет к усеченному целому числу вместо числа с плавающей запятой. Если этого не произойдет, скорее всего, он будет по умолчанию для операций с плавающей запятой. Это должно быть ожидаемое поведение со стороны программиста.
Просто имейте в виду, что здесь могут присутствовать и другие вещи, такие как уже упомянутый отдельный оператор целочисленного деления или неявное приведение типов.
источник
Есть много языков, где
((1/6)*6)
результат равен 1, а не 0. Например, PL / SQL, многие диалекты BASIC, Lua.Случайно, во всех этих языках 1/6 приводит к .166666667, или 0.16666666666667 или что-то подобное. Я выбрал вариант ((1/6) * 6) == 1, чтобы избавиться от этих небольших различий.
источник
((1/6)*6)==1
вариант, чтобы избавиться от этих небольших различий, но, похоже, я переоценил математические навыки некоторых людей.Haskell рассматривает 1/6 и 1,0 / 6,0 как тождественно 0,16666666666666666. Он также отображает 1 / 6.0 и 1.0 / 6 как одно и то же значение.
Это связано с тем, что базовые числовые типы в Haskell не совпадают с другими языками. Истинное целочисленное деление несколько ... сложно.
источник
Да, Perl делает. Однострочник
В результате получается:
Я считаю, что PHP работает так же.
Отредактировано, чтобы добавить: я также считаю, что необходимым (но не достаточным) условием
1/6 == 1.0/6.0
является слабая типизация рассматриваемого языка.источник
/
автоматически перегружается в зависимости от типов аргументов, но это выглядит как нарушение принципа наименьшего удивления для я ...В Squeak Smalltalk
/
по целым числам создаются объекты Fraction. Таким образом, хотя это не то же самое, что и деление с плавающей точкой, все равно(1/6)*6
возвращается 1.источник
Да, я только что проверил мой TI-99 / 4A , встроенный в TI BASIC . Поскольку все числовые выражения рассматриваются как плавающая точка, операция деления также является плавающей точкой.
источник
VB ( VB.Net , VB6 , VBA ...)
Целочисленный оператор деления
источник
MATLAB. Числовые литералы являются двойными по умолчанию.
источник
Clojure использует дроби по умолчанию. Это не то же самое, что 1.0 / 6.0, но вы можете конвертировать в него с помощью
float
илиdouble
когда вам нужно.источник
Удивительно, но в Windows PowerShell (версия 3) он работает правильно .
Также, похоже, работает в Python 3, как упоминалось sepp2k. Два других языка, которые у меня есть в наличии на REPL, Scala и Ruby, оба делят целочисленные и дают 0.
источник
Язык Rexx всегда дает арифметически правильный ответ. Например: 5/2 = 2,5. Rexx - отличный язык, который не был использован достаточно. Теоретически, когда компилятор не может определить, что вы хотите, лучше сделать правильную математику, однако это может быть неэффективно. Rexx также предоставляет оператор //.
источник