Описание
Поглощение операнда плавающего происходит, когда один операнд операции сложения или операции вычитания является всегда незначительно маленьким по сравнению с другим операндом. Поэтому результат операции всегда равен значению большего операнда, сокращая операцию.
Риск
Избыточные операции тратят впустую циклы выполнения вашего процессора.
Поглощение операнда плавающего может указать на проблемы проекта в другом месте в коде. Возможно, что разработчик ожидал различную область значений для одного из операндов и не ожидал сокращения операции. Однако область значений операнда отличается от того, что разработчик ожидает из-за проблем в другом месте в коде.
Фиксация
Смотрите, являются ли области значений операнда тем, что вы ожидаете. Чтобы видеть области значений, установите свой курсор на операцию.
Если области значений - то, что вы ожидаете, выравниваете по ширине, почему вы имеете в распоряжении избыточную операцию. Например, код только частично записан, и вы ожидаете другие значения для одного или обоих из операндов из будущего незаписанного кода.
Если вы не можете выровнять по ширине избыточную операцию, удалите ее.
Если области значений не то, что вы ожидаете, в вашем коде, прослеживаете, чтобы видеть, куда области значений прибывают из. Чтобы начать ваш traceback, ищите экземпляры операнда в вашем коде. Просмотрите предыдущие экземпляры операнда и определите, где неожиданная область значений происходит.
Чтобы определить, когда один операнд незначителен по сравнению с другим операндом, дефект использует правила на основе стандартов 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);
}
Исправление — проверяет область значений операнда
Другое возможное исправление должно видеть, являются ли области значений операнда тем, что вы ожидаете. Например, если одна из области значений операнда, как предполагается, не является незначительно маленькой, устраните проблему, вызывающую маленькую область значений. В следующем исправленном коде область значений (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);
}