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;
}
 Yamaneko31 окт. 2012 г., 18:59
@ Крис: так быстро!
 chris31 окт. 2012 г., 19:00
@VictorHugo, название отдает его. Конечно, это означает, что это очень хороший заголовок ».
 Robᵩ31 окт. 2012 г., 19:20
потому что 2/3 или 2,5 / 6 дают результаты " - Показать мне, как2/3 дает результат, отличный от.0
 chris31 окт. 2012 г., 18:58
Передайте привет целочисленному усечению.

Ответы на вопрос(3)

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

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

double k1 = 1/60.0; //Should work

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

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

double k2 = 1/(double)myDenom;
 Andy Ibanez31 окт. 2012 г., 19:23
О, я могу поклясться, что это должен быть знаменатель. Тот'Это то, что я помню из колледжа много лет назад.
 Robᵩ31 окт. 2012 г., 19:22
По крайней мере один из числителя или знаменателя должен иметь тип с плавающей запятой. Это недолжен быть знаменатель:1.0/60 тоже отлично работает.
Решение Вопроса

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

Исправление

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

делая этоdouble literal2 (60 целое число,60.0 или даже60. является ,double60.f является )floatиспользуя приведение (,double(60)(double)60).

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

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

но я'Я назначаю это! "double

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

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

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

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

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

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

Ваш ответ на вопрос