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

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

  •  23-09-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

В системах 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;
}

В использовании:


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 result меняет результат того же деления.Аналогично вы можете обрабатывать обычное деление на ноль (например,если вы не хотите, чтобы в результате получилась бесконечность).

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

Другие советы

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

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

DBL_MIN — наименьший двухместный номер.

DBL_EPSILON — наименьший двойной s.t.х+DBL_EPSILON != х

Поэтому я бы попробовал

#include <float.h>
#define EPS DBL_MIN

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

ИЭЭЭ 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);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top