Почему результат деления между двумя целыми усекается?

все опытные программисты в C# (я думаю, что это происходит от C) используются для приведения целых чисел в делении, чтобы получить результат decimal / double / float вместо int (реальный результат усечен).

Я хотел бы знать, почему это реализовано так? Есть ли веская причина усечь результат, если оба числа являются целыми?

6 ответов


C# прослеживает свое наследие до C, поэтому ответ на "почему это так в C#?"является ли комбинация "почему это так в C?"и" разве не было веской причины измениться?"

подход C должен иметь довольно тесное соответствие между языком высокого уровня и операциями низкого уровня. Процессоры обычно реализуют целочисленное деление как возвращающее частное и остаток, оба из которых имеют тот же тип, что и операнды.

(так что мой вопрос будет: "почему целочисленное деление в C-подобных языках не возвращает два целых числа", а не "почему он не возвращает значение с плавающей запятой?")

решение состояло в том, чтобы предоставить отдельные операции для деления и остатка, каждый из которых возвращает целое число. В контексте C неудивительно, что результатом каждой из этих операций является целое число. Это часто точнее чем арифметика с плавающей точкой. Рассмотрим пример из вашего комментария 7 / 3. Это значение не может быть представлено конечным двоичным числом ни конечным десятичным числом. Другими словами, на сегодняшних компьютерах,мы не можем точно представлять 7 / 3 если мы используем целые числа! Наиболее точным представлением этой дроби является "фактор 2, остаток 1".

итак, не было ли веской причины меняться? Я ничего не могу придумать, и я ... --10-->can подумайте о нескольких веских причинах не изменить. Ни один из других ответов не упомянул Visual Basic, который (по крайней мере, через версию 6) имеет два оператора для деления целых чисел: / преобразует целые числа в double и возвращает double, в то время как \ выполняет нормальную целочисленную арифметику.

я узнал о \ оператор после борьбы за реализацию бинарного алгоритма поиска с использованием деления с плавающей запятой. Это было действительно больно, и целочисленное деление вошло, как глоток свежего воздуха воздух. Без него было много специальной обработки для покрытия краевых случаев и отдельных ошибок в первом проекте процедуры.

из этого опыта я делаю вывод, что наличие разных операторов для деления чисел сбивает с толку.

другой альтернативой было бы иметь только одну целочисленную операцию, которая всегда возвращает double и требует, чтобы программисты усекли ее. Это означает, что вы должны выполнить два преобразования int - >double, усечение и преобразование double - >int каждый раз, когда вы хотите целочисленное деление. И сколько программистов ошибочно округлят или уменьшат результат вместо того, чтобы усечь его? Это более сложная система, и, по крайней мере, так же подвержена ошибкам программиста и медленнее.

наконец, в дополнение к двоичному поиску существует множество стандартных алгоритмов, использующих целочисленную арифметику. Одним из примеров является разделение коллекций объектов на подобласти одинакового размера. Другой-преобразование между индексами в a 1-d массив и координаты в 2-d матрице.

насколько я вижу, никакая альтернатива "int / int дает int" не выживает анализ затрат и выгод с точки зрения удобства использования языка, поэтому нет причин изменять поведение, унаследованное от C.

в заключение:

  • целочисленное деление часто полезно во многих стандартных алгоритмах.
  • когда требуется деление целых чисел с плавающей запятой, его можно вызвать явно с помощью простого, короткий и четкий бросок:(double)a / b, а не a / b
  • другие альтернативы вводят больше усложнения как программиста, так и большего количества тактовых циклов для процессора.

есть ли веская причина для усечения результата, если оба числа являются целыми?

конечно; я могу легко придумать дюжину таких сценариев. Например: у вас есть большое изображение и уменьшенная версия изображения, которая в 10 раз меньше в обоих измерениях. Когда пользователь нажимает на точку на большом изображении, вы хотите определить соответствующий пиксель в уменьшенном изображении. Ясно, что для этого вы делите координаты x и y на 10. Почему? хотели бы вы получить результат в десятичных? Соответствующие координаты будут целочисленными координатами в растровом изображении эскиза.

двойники отлично подходят для физических расчетов, а десятичные-для финансовых расчетов, но почти вся работа, которую я делаю с компьютерами, которые делают любую математику вообще, делает это полностью в целых числах. Я не хочу постоянно преобразовывать двойные или десятичные числа обратно в целые только потому, что я сделал некоторое деление. Если ты ... решение физических или финансовых проблем тогда почему вы используете целые числа в первую очередь? использовать ничего но двойники или десятичные дроби. Используйте целые числа для решения задач конечной математики.


вычисление на целых числах быстрее (обычно), чем на значениях с плавающей запятой. Кроме того, все остальные операции integer / integer (+, -, *) возвращает целое число.

изменить: По запросу ОП, вот этого:

проблема OP в том, что они думают о / как деление в математическом смысле, так и / оператор на языке выполняет некоторую другую операцию (которая не является математикой. отдел.) По этой логике они должны вопрос о правомерности всех других операций (+, -, *), так как у них есть специальные правила переполнения, что не то же самое, что ожидалось бы от их математических коллег. Если это кого-то беспокоит, они должны найти другой язык, где операции выполняются так, как ожидалось человеком.

Что касается претензии на разницу производительности в пользу целочисленных значений: когда я писал ответ, у меня были только "народные" знания и "интуиция", чтобы поддержать претензия (hece мой "обычно" отказ от ответственности). Действительно, как отметил Гейб, есть платформы, где это не выполняется. С другой стороны, я нашел вот это!--15-->ссылке (пункт 12), который показывает смешанные представления на платформе Intel (используемый язык-Java).

вынос должен быть тем, что с производительностью многие претензии и интуиция необоснованны, пока не измерены и не найдены истинными.


да, если конечный результат должен быть целым числом. Это будет зависеть от требований.

Если это действительно ваши требования, то вы не хотите хранить десятичное, а затем обрезать его. Вы будете тратить память и время на обработку, чтобы выполнить то, что уже встроено в функциональность.


оператор предназначен для возврата того же типа, что и вход.

Edit (ответ комментария): Почему? Я не разрабатываю языки, но я бы предположил, что большую часть времени вы будете придерживаться типов данных, с которых вы начали, и в оставшемся случае, какие критерии вы бы использовали для автоматического предположения, какой тип хочет пользователь? Вы бы автоматически ожидали строку, когда вам это нужно? (искренность намеренно)


Если вы добавляете int к int, вы ожидаете получить int. Если вы вычитаете int из int, вы ожидаете получить int. Если вы умножаете int на int, вы ожидаете получить int. Так почему бы вам не ожидать результата int, если вы разделите int на int? И если вы ожидаете int, то вам придется усечь.

Если вы этого не хотите, то сначала вам нужно бросить свои Инты на что-то другое.

Edit: я бы также отметил, что если вы действительно хотите понять, почему это, то вы должны начать смотреть, как работает двоичная математика и как она реализуется в электронной схеме. Конечно, нет необходимости разбираться в деталях, но краткий обзор этого действительно поможет вам понять, как низкоуровневые детали аппаратного обеспечения фильтруются до деталей языков высокого уровня.