деление — C ++. Деление 1 на любое число дает 0

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

Мой код:

int main()
{
double k1 = 1/60;
cout << k1
<< endl;
double k2 = 1/(60*60);
cout << k2
<< endl;

return 0;
}

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

5

Решение

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

Исправление

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

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

Лично я предпочитаю использовать напрямую double литералы — не то, что приведение имеет какое-либо ухудшение производительности на полпути приличных компиляторов, но оно кажется «неправильным» и многословным в отношении только использования литерала правильного типа. (Очевидно, когда оба операнда являются переменными, а не литералами вы иметь использовать актерский состав)

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

  • «но я назначаю это double

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

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

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

    Несколько языков автоматически выполняют деление с плавающей запятой, даже когда аргументы являются целыми числами (например, VB6, IIRC), поскольку оно кажется более интуитивным для новичков. В C / C ++ это не так: деление является целочисленным, когда аргументы целочисленные, поскольку во многих случаях вы просто не заботитесь о десятичных дробях, и / или по соображениям производительности предпочтительно не использовать FPU (фоновая философия в C и C ++ это «вы не платите за то, что не используете»).

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


  1. Угол Nitpickers: да, здесь на самом деле это инициализация, а не назначение, но мы говорим о том же заблуждении.
  2. «Литерал» — это значение, включенное в исходный код.
9

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

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

2

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

double k1 = 1/60.0; //Should work

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

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

double k2 = 1/(double)myDenom;
1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector