Pergunta

Qual é a melhor maneira de usar NaNs em C ++?

Eu encontrei std::numeric_limits<double>::quiet_NaN() e std::numeric_limits<double>::signaling_NaN(). Eu gostaria de usar signaling_NaN para representar uma variável não inicializada da seguinte forma:

double diameter = std::numeric_limits<double>::signaling_NaN();

Isso, no entanto, sinais (levanta uma exceção) em missão. Eu quero isso para levantar uma exceção em uso, e não em missão.

Existe alguma maneira de usar signaling_NaN sem levantar uma exceção em missão? Existe uma boa, alternativa portátil para signaling_NaN que irá levantar uma exceção de ponto flutuante quando usado?

Foi útil?

Solução

Depois de olhar para isso um pouco mais, parece que signaling_NaN é inútil, como previsto. Se flutuante exceções de ponto estão habilitados, em seguida, chamando ele conta como o processamento de um NaN sinalização, por isso imediatamente levanta uma exceção. Se flutuante exceções de ponto são pessoas com deficiência, em seguida, o processamento de um NaN sinalização automaticamente rebaixa-lo para uma tranquila NaN, então signaling_NaN não funciona de qualquer maneira.

código de Menkboy obras, mas tentando usar sinalização NANS é executado em outros problemas: não há nenhuma maneira portátil para ativar ou desativar exceções de ponto flutuante (como aludido aqui e aqui ), e se você está confiando em exceções sendo ativado , código de terceiros pode desativá-los (como descrito aqui ).

Assim, parece que Motti é realmente a melhor escolha.

Outras dicas

O sinalização meios NAN é que, quando os encontros de CPU que um sinal é disparado, (daí o nome). Se você deseja detectar variáveis ??não inicializadas, em seguida, elevar o nível de alerta em seu compilador normalmente detecta todos os caminhos que usam valores uninitalized. Se isso falhar, você pode usar uma classe wrapper que armazena um boolean dizendo se o valor é inicializado:

template <class T>
class initialized {
    T t;
    bool is_initialized;
public:
    initialized() : t(T()), is_initialized(false) { }
    initialized(const T& tt) : t(tt), is_initialized(true) { }
    T& operator=(const T& tt) { t = tt; is_initialized = true; return t; }
    operator T&() {
         if (!is_initialized)
             throw std::exception("uninitialized");
         return t; 
   }
};

Você pode escrever um NaN sinalização em uma variável sem disparar uma exceção com algo como isto (nb: não testado)

void set_snan( double &d )
{
    long long *bits = (long long *)&d;
    *bits = 0x7ff0000080000001LL;
}

Ele vai trabalhar a maioria dos lugares, mas não, não é 100% portátil.

Bem, procurando após a definição de ambos tranquila e sinalização NaN, eu não posso realmente fazer qualquer diferença.

Você pode usar o código que é usado nessas funções a si mesmo, talvez ele impede que uma exceção dessa maneira, mas não vendo nenhuma exceção nessas duas funções, acho que pode estar relacionado com outra coisa.

Se você deseja atribuir diretamente o NaN:

double value = _Nan._Double;

A resposta é simples: Fazer algo assim no cabeçalho do arquivo e usá-lo em qualquer outro lugar:

#define NegativeNaN log(-1)

Se você quiser fazer algum tipo de manipulações sobre eles melhor escrever alguma função de invólucro estendido em torno exp() como extended_exp() e assim por diante!

A implementação C ++ pode ter uma API para acessar o ambiente de ponto flutuante para testar e certas exceções de ponto flutuante claras. Consulte minha resposta a uma pergunta relacionada para obter mais informações.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top