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