Как заставить 0.0 / 0.0 возвращать ноль вместо NaN в компиляторе MIPSPro C? - PullRequest
5 голосов
/ 02 апреля 2010

Как говорится в вопросе, я использую компилятор C MIPSPRo, и у меня есть операция, которая будет возвращать NaN для некоторых наборов данных, где числитель и деном равен нулю. Как мне избежать этого?

Ответы [ 4 ]

9 голосов
/ 02 апреля 2010

В системах SGI с компилятором MIPSPro вы можете с большой точностью установить обработку различных исключений с плавающей запятой, используя средства sigfpe.h.Как это бывает, деление нуля на ноль является одним из таких случаев:

#include <stdio.h>
#include <sigfpe.h>

int main (void) {
    float x = 0.0f;
    (void) printf("default %f / %f = %f\n", x, x, (x / x));
    invalidop_results_[_ZERO_DIV_ZERO] = _ZERO;
    handle_sigfpes(_ON, _EN_INVALID, 0, 0, 0);
    (void) printf("handled %f / %f = %f\n", x, x, (x / x));
    return 0;
}

Используется:

<code>
arkku@seven:~/test$ cc -version
MIPSpro Compilers: Version 7.3.1.3m
arkku@seven:~/test$ cc -o sigfpe sigfpe.c -lfpe
arkku@seven:~/test$ ./sigfpe
default 0.000000 / 0.000000 = nan0x7ffffe00
handled 0.000000 / 0.000000 = 0.000000

Как видите,установка результата _ZERO_DIV_ZERO изменяет результат того же деления.Точно так же вы можете обрабатывать регулярное деление на ноль (например, если вы не хотите бесконечность в качестве результата).

Конечно, ничего из этого не является стандартным;было бы более удобно проверять NaN после каждого деления, а еще лучше проверять нули перед этим.C99 предлагает некоторый контроль над средой с плавающей точкой в ​​fenv.h, но я не думаю, что что-нибудь подходящее для этого доступно.В любом случае мой старый MIPSPro не поддерживает C99.

9 голосов
/ 02 апреля 2010

Использовать условие if? Также мне любопытно, почему вы хотите игнорировать эту математическую невозможность. Вы уверены, что ваш ввод не является неправильным / бессмысленным в этом случае?

1 голос
/ 02 апреля 2010

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

DBL_MIN является наименьшим двойным

DBL_EPSILON - наименьший двойной с.т. x + DBL_EPSILON! = x

Так что я бы попробовал

#include <float.h>
#define EPS DBL_MIN

double divModified(double num, double denom) {
    return num / (denom + EPS);
}
0 голосов
/ 04 апреля 2010

IEEE 754 (спецификация для плавающей запятой) говорит, что 0.0 / 0.0 не является числом, т.е. NaN. Если вы хотите, чтобы это было что-то еще, безусловно, лучший подход - это определить, когда оба операнда равны нулю в предложении if, и вернуть значение, которое вы бы предпочли дать. Возможно так:

#define WonkyDiv(a,b)  ((a)==0.0&&(b)==0.0 ? 0.0 : (a)/(b))

float wonkyResult = WonkyDiv(numerator, denominator);
...