Когда я пытаюсь разделить 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;
}
Я ценю вашу помощь.
Поскольку оба ваших операнда являются целыми числами, компилятор выполняет целочисленное деление (которое не вычисляет десятичную часть). Если хотя бы один из операндов является типом с плавающей запятой (как в других ваших примерах), другой получает повышение и выполняется деление с плавающей запятой.
Исправление
Сделайте хотя бы один из операндов типа с плавающей запятой (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 ++ как есть. 🙂
Линия double k1 = 1/60
будет оцениваться компилятором как константа времени компиляции. Поскольку в конце числа нет ‘.0’, 1/60
будет оцениваться через целочисленное деление и, следовательно, будет 0.
Знаменатель тоже должен быть десятичным числом.
double k1 = 1/60.0; //Should work
В противном случае ваша программа будет по существу обрезать все десятичные дроби.
МАЛЕНЬКИЙ ДОПОЛНИТЕЛЬНЫЙ: когда ваш знаменатель является переменной, вы должны привести его:
double k2 = 1/(double)myDenom;