Como forço 0,0/0,0 a retornar zero em vez de NAN no compilador MIPSPRO C?

StackOverflow https://stackoverflow.com/questions/2563418

  •  23-09-2019
  •  | 
  •  

Pergunta

Como afirma a pergunta, estou usando o compilador MIPSPRO C e tenho uma operação que retornará a NAN para alguns conjuntos de dados em que o numerador e o denom são zero. Como faço para impedir que isso aconteça?

Foi útil?

Solução

Nos sistemas SGI com o compilador MIPSPro, você pode definir o manuseio de várias exceções de ponto flutuante com grande precisão usando as instalações em sigfpe.h. Por acaso, a divisão de zero por zero é um desses casos:

#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;
}

Em uso:


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

Como você pode ver, definindo o _ZERO_DIV_ZERO Resultado altera o resultado da mesma divisão. Da mesma forma, você pode lidar com a divisão regular por zero (por exemplo, se você não quiser o infinito como resultado).

Obviamente, nada disso é padrão; Seria mais portátil verificar a NAN após cada divisão e ainda melhor verificar se há zeros antes. C99 oferece algum controle sobre o ambiente de ponto flutuante em fenv.h, mas não acho que algo adequado para isso esteja disponível. De qualquer forma, meu antigo MIPSPRO não suporta C99.

Outras dicas

Use uma cláusula if? Também estou curioso por que você gostaria de ignorar essa impossibilidade matemática. Você tem certeza de que sua entrada não está errada/sem sentido neste caso?

Se você não se importa de introduzir um pequeno erro, pode agregar um pequeno valor ao denominador, supondo que esteja fazendo aritmética de ponto flutuante. aparentemente tem alguns pequenos valores definidos:

Dbl_min é o menor duplo

Dbl_epsilon é o menor duplo st x+dbl_epsilon! = X

Então eu tentaria

#include <float.h>
#define EPS DBL_MIN

double divModified(double num, double denom) {
    return num / (denom + EPS);
}

IEEE 754 (A especificação para ponto flutuante) diz que 0,0/0,0 não é um número, ou seja, NaN. Se você deseja que seja mais alguma coisa, de longe a melhor abordagem é detectar quando os operando são zero em um if Cláusula e retorne o valor que você prefere dar. Talvez assim:

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

float wonkyResult = WonkyDiv(numerator, denominator);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top