Почему деление приводит к нулю вместо десятичного?

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

tempC=(.555*(tempF-32)) будет работать, но tempC=((5/9)*(tempF-32)) не будет работать.

Почему?
Согласно C Primer Plus, он должен работать, поскольку я использую float для tempC и tempF.

Ответы

Ответ 1

Похоже, у вас есть целочисленное деление во втором случае:

tempC=((5/9)*(tempF-32))

5 / 9 будет усекаться до нуля.

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

tempC=((5./9.)*(tempF-32))

Ответ 2

Другие уже говорили вам, что 5 и 9 являются целыми числами, и поэтому результат усекается.

Я добавлю объяснение для более глубокого понимания того, что действительно происходит между строк:

double tempC;
double tempF;
tempC = (5/9) * (tempF-32); // removed unnecessary parenthesis

В зависимости от того, какой порядок оценки (слева направо или справа налево) использует конкретный компилятор, он начнет (tempF-32) (5/9) или (tempF-32).

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


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

  • Правила приоритета операторов в Си определяют, какие операнды связаны с каким оператором. Оператор круглых скобок имеет наивысший приоритет в C, поэтому компилятор начнет с оценки содержимого первой обнаруженной круглой скобки.
  • Поэтому он начнется с выражения (5/9).
  • Компилятор проверяет тип каждого операнда.
  • В этом случае они оба являются константными целочисленными литералами. Целочисленные литералы 5 и 9 всегда имеют тип int в C.
  • Поскольку оба операнда имеют один и тот же тип, а это int, неявные преобразования типов не требуются.
  • Вычисление выполняется по типу int а результатом является int.

До сих пор выражение оценивается как:

tempC = (int)0 * (tempF-32);

  • Затем компилятор оценивает (tempF-32).
  • Типы операндов double и int. Они не того же типа.
  • Имеются неявные преобразования типов. В этом случае то, что называется балансировкой (формально называется обычными арифметическими преобразованиями).
  • Правила балансировки говорят, что если один тип является двойным, а другой - чем-то другим, другой тип должен быть преобразован в двойной.
  • После неявного преобразования типов выражение теперь эквивалентно (double)tempF - (double)32. Результат этого вычисляется и сохраняется во временной невидимой переменной типа double. Эта невидимая переменная хранится в регистре процессора или в стеке.

Теперь выражение можно описать как

tempC = (int)result1 * (double)result2;

где "result1" равен 0, а "result2" является результатом tempF - (double) 32.

  • Затем компилятор оценивает это новое выражение. Он находит int и double.
  • Снова происходит балансировка, и int конвертируется в double.
  • Умножение выполняется на два двойных, и в результате получается двойное.
  • Результат сохраняется в еще одной временной невидимой переменной.

tempC = (double)result3;

  • Компилятор оценивает это новое выражение. Он находит, что двойник должен быть сохранен внутри двойника. Это не проблема, поэтому не требуется никаких явных преобразований. "result3" сохраняется в tempC.

Ответ 3

Когда вы делаете 5/9, 5 и 9 - оба целых числа и целочисленное деление. Результатом целочисленного деления является целое число, и это фактор двух операндов. Итак, фактор в случае 5/9 равен 0, и поскольку вы умножаетесь на 0, tempC получается равным 0. Чтобы не иметь целочисленного деления, по крайней мере один из двух операндов должен быть float.

например. если вы используете 5.0/9 или 5/9.0 или 5.0/9.0, он будет работать, как ожидалось.

Ответ 4

5/9 - целочисленное деление, а не деление с плавающей запятой. Вот почему вы получаете неправильный результат.

Сделайте 5 или 9 переменных с плавающей запятой, и вы получите правильный ответ.

Подобно 5.0/9 OR 5/9.0

Ответ 5

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

Ответ 6

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

Вы можете изменить свое выражение так, чтобы сначала было преобразование в float:

tempC=((5/9)*(tempF-32));tempC=(5*(tempF-32))/9;

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