# V636. Expression was implicitly cast from integer type to real type. Consider using an explicit type cast to avoid overflow or loss of a fractional part.

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

Рассмотрим возможные ошибки на примерах.

Ситуация первая. Переполнение.

    int LX = 1000;
    int LY = 1000;
    int LZ = 1000;
    int Density = 10;
    double Mass = LX * LY * LZ * Density;

Мы хотим вычислить массу объекта, зная его плотность и размеры. Мы знаем, что результирующее значение может быть большим. Поэтому, переменная 'Mass' имеет тип 'double'. Однако этот код не учитывает, что перемножаются переменные типа 'int'. В результате, в правой части выражения произойдет целочисленное переполнение и результат будет некорректен.

Исправить ситуацию можно двумя способами. Можно изменить типы переменных:

    double LX = 1000.0;
    double LY = 1000.0;
    double LZ = 1000.0;
    double Density = 10.0;
    double Mass = LX * LY * LZ * Density;

Другой способ - это использовать явное приведение типов:

    int LX = 1000;
    int LY = 1000;
    int LZ = 1000;
    int Density = 10;
    double Mass = (double)(LX) * LY * LZ * Density;

Достаточно привести к типу 'double' только первую переменную. Поскольку операция умножения относится к лево-ассоциативным операторам, то вычисление будет происходить следующим образом: (((double)(LX) * LY) * LZ) * Density. В результате каждый из операндов перед умножением будет преобразовываться к типу 'double' и мы получим корректный результат.

P.S. Напомним, что вот так, делать неправильно: Mass = (double)(ConstMass) + LX * LY * LZ * Density. Выражение справа от оператора '=' будет иметь тип 'double'. Но перемножаться будут по-прежнему переменные типа 'int'.

Ситуация вторая. Потеря точности.

    int totalTime = 1700;
    int operationNum = 900;
    double averageTime = totalTime / operationNum;

Программист может ожидать, что переменная 'averageTime' будет иметь значение '1.888(8)', однако при выполнении программы будет получен результат равный '1.0'. Это происходит потому, что операция деления выполняется с целочисленными типами и только затем приводится к типу с плавающей точкой.

Как и в предыдущем случае, ошибку можно исправить 2 способами.

Первый способ - изменить типы переменных:

    double totalTime = 1700;
    double operationNum = 900;
    double averageTime = totalTime / operationNum;

Второй способ - использовать явное приведение типов.

    int totalTime = 1700;
    int operationNum = 900;
    double averageTime = (double)(totalTime) / operationNum;

Примечание

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

//-V636

См. также: Документация. Подавление ложных предупреждений.

Данная диагностика классифицируется как:

CWE-682 CERT-FLP06-C

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V636.