ПроблемаПоглощение поплавкового операнда происходит, когда один операнд операции сложения или вычитания всегда пренебрежимо мал по сравнению с другим операндом. Поэтому результат операции всегда равен значению большего операнда, что делает операцию избыточной.
РискИзбыточные операции тратят время на выполнение вашего процессора.
Поглощение поплавкового операнда может указывать на проблемы дизайна в других частях кода. Возможно, что разработчик ожидал другого диапазона для одного из операндов и не ожидал избыточности операции. Однако диапазон операндов отличается от ожидаемого разработчиком из-за проблем в других частях кода.
ЗафиксироватьПроверьте, какие диапазоны операндов вы ожидаете. Для просмотра диапазонов установите курсор на операцию.
Если диапазоны являются ожидаемыми, обосновайте, почему имеется избыточная операция. Например, код записывается только частично, и из будущего неписаного кода ожидаются другие значения для одного или обоих операндов.
Если избыточная операция не может быть оправдана, удалите ее.
Если диапазоны не являются ожидаемыми, в коде выполните обратную трассировку, чтобы увидеть, откуда берутся диапазоны. Чтобы начать трассировку, найдите экземпляры операнда в коде. Просмотрите предыдущие экземпляры операнда и определите место возникновения неожиданного диапазона.
Чтобы определить, когда один операнд пренебрежимо мал по сравнению с другим операндом, дефект использует правила, основанные на стандартах IEEE ® 754. Чтобы исправить дефект, вместо использования фактических правил можно использовать эту эвристику: отношение большего к меньшему операнду должно быть меньше, чем2p-1 по крайней мере для некоторых значений. Здесь, p равен 24 для 32-разрядной точности и 53 для 64-разрядной точности. Для определения точности дефект использует спецификацию для Target processor type (-target).
Этот дефект появляется, только если один операнд всегда пренебрежимо меньше другого операнда. Для просмотра экземпляров субнормальных операндов или результатов используйте флажок Субнормальное плавание в Prover™ кода Polyspace ®.
Пример - Один дополнительный операнд пренебрежительно меньше, чем другой операнд#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);
}