Как сделать целочисленное деление в c

Добавил пользователь Евгений Кузнецов
Обновлено: 05.10.2024

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

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

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

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

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

  • целочисленное деление
  • деление с плавающей запятой
  • десятичное деление

в вашем случае мы имеем целочисленное деление со следующими правилами:

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

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

или, если вы используете литералы:

имейте в виду, плавающие точки не являются точными. Если вы заботитесь о точности, то используйте тип decimal, а не.

поскольку вы не используете суффикс, литералы 13 и 4 интерпретируется как целое число:

инструкцию:

если литерал не имеет суффикса, то есть первый из этих типов, в которых его значение может быть представлено: int , uint , long , ulong .

таким образом, поскольку вы объявляете 13 в качестве целого числа будет выполнено целочисленное деление:

инструкцию:

для операции формы x / y применяется разрешение перегрузки двоичного оператора для выбора конкретной реализации оператора. Операнды преобразуются в типы параметров выбранного оператора, а тип результата является типом возвращаемого оператором.

предопределенные операторы деления перечислены ниже. Все операторы вычисляют фактор x и y.

целое число разделение:

и так округление происходит:

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

если вы делаете следующий:

вы получите ошибку компилятора, так как деление с плавающей запятой ( / оператор 13f ) приводит к float, который не может быть приведен к int неявно.

если вы хотите, чтобы деление было делением с плавающей запятой, вам нужно будет сделать результат float:

обратите внимание, что вы все равно будете делить целые числа, которые неявно будут брошены в float: результат будет 3.0 . Явное объявление операндов как float, используя f суффикс ( 13f , 4f ).

просто основные операции.

помните, когда вы научились делить. В начале мы решили 9/6 = 1 with remainder 3 .

оператор / - в сочетании с оператором % - используются для извлечения этих значений.

может быть полезно:

результат всегда будет иметь тип, который имеет больший диапазон числителя и знаменателя. Исключения-байтовые и короткие, которые производят int (Int32).

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

Когда я пытаюсь разделить 1/60 или 1 / (60 * 60), это дает 0. Даже в окне отладчика. Я немного запутался, что это может быть, потому что 2/3 или 2,5 / 6 дают результаты.

Я ценю вашу помощь.

Решение

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

Исправление

Сделайте хотя бы один из операндов типа с плавающей запятой ( double или же float ); Вы можете сделать это, например:

  • делая это double буквальный 2 ( 60 целое число, 60.0 или даже 60. является double , 60.f является float )
  • используя актерский состав ( double(60) , (double)60 ).

Общие возражения

Многие новички смущены этим фактом, так как считают, что 1 результат к double должно быть какой-то подсказкой компилятору. На самом деле это не так.

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

почему нужно целочисленное деление?

Очевидно, что проблему можно было бы решить с помощью отдельного оператора для интегрального деления (VB, опять же, использует \ ), но ИМХО у нас достаточно операторов в C ++ как есть. 🙂

Другие решения

Линия double k1 = 1/60 будет оцениваться компилятором как константа времени компиляции. Поскольку в конце числа нет ‘.0’, 1/60 будет оцениваться через целочисленное деление и, следовательно, будет 0.

Знаменатель тоже должен быть десятичным числом.

В противном случае ваша программа будет по существу обрезать все десятичные дроби.

МАЛЕНЬКИЙ ДОПОЛНИТЕЛЬНЫЙ: когда ваш знаменатель является переменной, вы должны привести его:


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

  • выберите первую цифру;
  • если меньше делимого, берете вторую и т.е. пока не будет число больше того, на которое надо делить;
  • тут надо подцикл:
    • надо умножать числа от 1 до 9 на делимое до тех пор, пока не получите число > делимого => предыдущее число и есть ваше; в примере на первой итерации получим 1-ку, т.к. 2*7 = 14 > 13 нам не подходит
    • вычитаем из нашего числа (в примере 13) то, что при умножении вышло 1*7 : получим 6 и снова в начало итерации к 6 прибавляем новую цифру
    • тут нацело не делится остаток 6.

    Я подал идею, даже блок схему не написал по нормальному, - но, скорее всего, она не так тяжело реализуется, хотя нужна внимательность. :) Успехов.

    Строго говоря, целочисленного деления не существует (деление по определению - это операция, производящая рациональное число, целые числа - очень небольшое подмножество этого числа).

    Я думаю, вы имеете в виду рациональные числа . См. Википедию : деление двух целых чисел может привести к получению остатка. Чтобы завершить деление остатка, система счисления расширяется и включает дроби или рациональные числа, как их обычно называют.

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

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

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

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

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

    • Целочисленное деление
    • Деление с плавающей точкой
    • Десятичное деление

    В вашем случае у нас есть целочисленное деление со следующими правилами:

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

    Каждый тип данных может перегрузить каждый оператор. Если и числитель, и знаменатель являются целыми числами, целочисленный тип выполнит операцию деления и вернет целочисленный тип. Если вы хотите деление с плавающей запятой, вы должны привести одно или несколько чисел к типам с плавающей запятой, прежде чем делить их. Например:

    или, если вы используете литералы:

    Имейте в виду, что числа с плавающей запятой неточны. Если вам важна точность, используйте вместо этого что-то вроде десятичного типа.

    +1 за упоминание о том, что для деления с плавающей запятой необходимо использовать только один член.

    Очевидно, что ваше утверждение о точности является правильным в контексте обучения и делает его несложным для понимания. Поскольку нам нужно быть максимально точными в нашей работе, я все же хочу уточнить точность: согласно IEE 754-1985 вы МОЖЕТЕ получить точный результат (хотя в большинстве случаев это не так). Вы можете получить точный результат, если ранее были представлены точные значения вычислений, и результат представляет собой, попросту говоря, сумму степеней 2. Даже при том, что не может быть лучшей практикой полагаться на эту точность в этих особых случаях.

    Дополнение к точности: вероятность получения точного результата резко улучшается, когда результат приближается к 1 или -1. Это может немного сбивать с толку, что эта вероятность все еще остается 0, поскольку существует бесконечное число и конечное число результатов, которые можно представить точно. :)

    Десятичные дроби неточны по тем же причинам, что и числа с плавающей запятой; просто числа с плавающей точкой имеют основание 2, а десятичные числа - основание 10. Например, десятичный тип не может точно содержать точное значение 1/3.

    Поскольку вы не используете суффикс, литералы 13 и 4 интерпретируются как целые числа:

    Руководство :

    Если буквальное не имеет суффикса, он имеет первый из этих типов , в которых его значение может быть представлено: int , uint , long , ulong .

    Таким образом, поскольку вы объявляете 13 целое число, будет выполнено целочисленное деление:

    Руководство :

    Для операции формы x / y применяется разрешение перегрузки бинарного оператора, чтобы выбрать конкретную реализацию оператора. Операнды преобразуются в типы параметров выбранного оператора, а тип результата - это тип, возвращаемый оператором.

    Предварительно определенные операторы деления перечислены ниже. Все операторы вычисляют частное x и y.

    Целочисленное деление:

    И так происходит округление в меньшую сторону:

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

    Если вы сделаете следующее:

    Вы получите ошибку компилятора, поскольку деление с плавающей запятой ( / оператор of 13f ) приводит к получению числа с плавающей запятой, которое не может быть неявно преобразовано в int.

    Если вы хотите, чтобы деление было делением с плавающей запятой, вам нужно сделать результат с плавающей запятой:

    Обратите внимание, что вы по-прежнему делите целые числа, которые неявно будут преобразованы в float: результат будет 3.0 . Чтобы явно объявить операнды как float, используя f суффикс ( 13f , 4f ).

    +1 за объяснение того, что вы можете получить ответ в виде числа с плавающей запятой, но при этом выполнять целочисленное деление. Кроме того, я видел еще один распространенный способ принудительного деления с плавающей запятой - это умножение первого члена деления на 1.0 .

    Это просто базовая операция .

    Вспомните, когда вы научились делить. Вначале мы решили 9/6 = 1 with remainder 3 .

    Оператор / в сочетании с оператором% используются для получения этих значений.

    Читайте также: