Pergunta

Eu estou querendo encontrar o número de dígitos mantissa ea unidade de arredondamento em um computador particular. Eu tenho uma compreensão de que estes são, apenas nenhuma idéia de como encontrá-los - embora eu entendo que pode variar de computador para computador.

Eu preciso este número, a fim de realizar certos aspectos da análise numérica, como erros de análise.

O que eu estou pensando no momento é que eu poderia escrever um programa pequeno c ++ lentamente incrementar um número até que ocorra excesso, mas eu não tenho certeza que tipo de número para uso.

Am I no caminho certo? Como exatamente se faz para calcular isso?

Foi útil?

Solução

Gostaria de pensar que qualquer linguagem que você estava usando seria especificar como carros alegóricos foram armazenados. Eu sei que Java faz isso através da utilização de um padrão IEEE específico (754, eu acho).

Se não for especificado, eu acho que você poderia apenas fazer o seu próprio check adicionando 0,5 a 1 para ver se as mudanças de números reais. Se isso acontecer, em seguida, adicione 0,25 a 1, a 0,125 a 1, e assim por diante até que o número não muda, algo como:

float a = 1;
float b = 0.5;
int bits = 0;
while (a + b != a) {
    bits = bits + 1;
    b = b / 2;
}

Se você só tinha 3 bits mantissa, então 1 + 1/16 seria igual a 1.

Em seguida, você já esgotou seus bits mantissa.

Você realmente pode precisar o número base para ser 2 em vez de 1, desde IEEE754 usa um implícita '1+' no início.

EDIT:

Parece que o método descrito acima pode ter alguns problemas, pois dá 63 bits para um sistema que claramente tem flutuadores de 4 bytes.

Se isso é fazer com resultados intermediários (duvido que uma vez que o mesmo código com conversões explícitas [while (((float)(a + b) != (float)(a))] tem problemas semelhantes) ou (mais provável, creio eu) a possibilidade de que o valor unitário a pode ser representado com pedaços mais perto o b fracionada ajustando o expoente, eu não sei ainda.

Por enquanto, é melhor confiar na informação língua que eu mencionei acima, tais como o uso de IEEE754 (se essa informação está disponível).

Vou deixar o código problemático na como uma armadilha para os jogadores cautelosos. Talvez alguém com conhecimento ponto mais flutuante, então eu posso deixar uma nota explicando por que ele age de forma estranha (sem conjectura, por favor: -).

EDIT 2:

Este pedaço de código resolve o problema, garantindo intermediários são armazenados em carros alegóricos. Acontece que Jonathan Leffler estava certo - era resultados intermediários

.
#include <stdio.h>
#include <float.h>

int main(void) {
    float a = 1;
    float b = 0.5;
    float c = a + b;
    int bits = 1;
    while (c != a) {
        bits = bits + 1;
        b = b / 2;
        c = a + b;
    }
    printf("%d\n",FLT_MANT_DIG);
    printf("%d\n",bits);
    return 0;

}

Esta saídas de código (24,24) para mostrar que o valor calculado corresponde a um no cabeçalho do arquivo.

Apesar de escrito em C, deve ser aplicável a qualquer idioma (especificamente aquele em que a informação não está disponível em um cabeçalho ou em virtude de que é especificado na documentação do idioma). Eu só testado em C porque Eclipse leva tanto tempo para começar na minha caixa de Ubuntu: -).

Outras dicas

Para C, e, por extensão, C ++, a informação está nas <float.h> ou <cfloat> cabeçalhos.

Para C99, a informação está na seção 5.2.4.2.2 do padrão:

  • FLT_RADIX
  • FLT_MANT_DIG
  • FLT_DIG
  • FLT_EPSILON
  • FLT_MIN_EXP
  • FLT_MIN
  • FLT_MIN_10_EXP
  • FLT_MAX_EXP
  • FLT_MAX
  • FLT_MAX_10_EXP
variações

E da mesma forma para DBL e LDBL sobre a maioria destes (sem DBL_RADIX ou LDBL_RADIX). O padrão sugere valores apropriados para IEEE 754 (a versão mais antiga do padrão IEEE 754 que era atual, em 1999, houve uma nova versão publicada em, creio eu, 2008).

Você pode querer verificar para fora <limits> em sua biblioteca C ++:

#include <iostream>
#include <limits>
#include <typeinfo>

template <typename T>
void printDetailsFor() {
    std::cout
        << "Printing details for " << typeid(T).name() << ":\n"
        << "\tradix:        " << std::numeric_limits<T>::radix        << "\n"
        << "\tradix digits: " << std::numeric_limits<T>::digits       << "\n"
        << "\tepsilon:      " << std::numeric_limits<T>::epsilon()    << "\n"
        << std::endl;
}

int main() {
    printDetailsFor<int>();
    printDetailsFor<float>();
    printDetailsFor<double>();
    printDetailsFor<long double>();
    return 0;
}

Eu acho que você quer std::numeric_limits<T>::digits que deve ser mais um do que o número de bits de mantissa. Minha máquina imprime:

Printing details for i:
    radix:        2
    radix digits: 31
    epsilon:      0

Printing details for f:
    radix:        2
    radix digits: 24
    epsilon:      1.19209e-07

Printing details for d:
    radix:        2
    radix digits: 53
    epsilon:      2.22045e-16

Printing details for e:
    radix:        2
    radix digits: 64
    epsilon:      1.0842e-19
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top