exponenta event banner

Absorption of float operand

Один операнд сложения или вычитания поглощается другим операндом

Описание

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

Риск

Резервные операции теряют циклы выполнения вашего процессора.

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

Зафиксировать

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

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

    Если вы не можете обосновать избыточную операцию, удалите ее.

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

Чтобы определить, когда один операнд незначителен по сравнению с другим операндом, дефект использует правила, основанные на IEEE® 754 стандарта. Чтобы исправить дефект, вместо использования фактических правил можно использовать этот эвристический: отношение большего к меньшему операнду должно быть меньше 2p-1 по крайней мере, для некоторых значений. Здесь, p равно 24 для 32-битной точности и 53 для 64-битной точности. Чтобы определить точность, дефект использует вашу спецификацию для Target processor type (-target).

Этот дефект появляется только, если один операнд всегда незначительно меньше, чем другой операнд. Чтобы увидеть образцы субнормальных операндов или результатов, используйте Subnormal Float проверки в Polyspace® Code Prover™.

Примеры

расширить все

#include <stdlib.h>

float get_signal(void);
void do_operation(float);

float input_signal1(void) {
    float temp = get_signal();
    if(temp > 0. && temp < 1e-30)
        return temp;
    else {
       /* Reject value */    
       exit(EXIT_FAILURE);
    }
}

float input_signal2(void) {
    float temp = get_signal();
    if(temp > 1.)
        return temp;
    else {
       /* Reject value */    
       exit(EXIT_FAILURE);
    }
}

void main() {
    float signal1 = input_signal1();
    float signal2 = input_signal2();
    float super_signal = signal1 + signal2;
    do_operation(super_signal);
}

В этом примере дефект появляется на сложение, потому что операнд signal1 находится в области значений (0,1e-30) но signal2 больше 1.

Коррекция - Удаление избыточной операции

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

#include <stdlib.h>

float get_signal(void);
void do_operation(float);

float input_signal1(void) {
    float temp = get_signal();
    if(temp > 0. && temp < 1e-30)
        return temp;
    else {
       /* Reject value */    
       exit(EXIT_FAILURE);
    }
}

void main() {
    float signal1 = input_signal1();
    do_operation(signal1);
}
Коррекция - Проверьте область значений операнда

Еще одна возможная коррекция - увидеть, являются ли области значений operand тем, что вы ожидаете. Для образца, если один из области значений операнда не должен быть незначительно маленьким, исправьте проблему, вызывающую малую область значений. В следующем исправленном коде область значений (0,1e-2) навязывается signal2 так что он не всегда незначительно мал по сравнению с signal1.

#include <stdlib.h>

float get_signal(void);
void do_operation(float);

float input_signal1(void) {
    float temp = get_signal();
    if(temp > 0. && temp < 1e-2)
        return temp;
    else {
       /* Reject value */    
       exit(EXIT_FAILURE);
    }
}

float input_signal2(void) {
    float temp = get_signal();
    if(temp > 1.)
        return temp;
    else {
       /* Reject value */    
       exit(EXIT_FAILURE);
    }
}

void main() {
    float signal1 = input_signal1();
    float signal2 = input_signal2();
    float super_signal = signal1 + signal2;
    do_operation(super_signal);
}

Информация о результатах

Группа: Численный
Язык: C | C++
По умолчанию: On
Синтаксис командной строки: FLOAT_ABSORPTION
Влияние: Высокий
ИДЕНТИФИКАТОР CWE: 189, 682, 873
Введенный в R2016b