Pergunta

Estou seguindo alguns tutoriais iniciantes para o OpenGL no C ++, mas quando comecei como programador AC#, isso me fez dar muitas coisas como garantidas. Então, meu problema ocorreu quando eu deprava a impressão da minha leitura de FPS na saída. Eu acho que o método era algo como DebugPrintString do topo da minha cabeça, que levava um char* e basicamente eu estava imprimindo "FPS: X". Eu estava usando o scanf_s para colocar o valor do FPS na matriz de caracteres, mas é aí que está meu problema. Qual o tamanho da matriz do personagem?

Deixe -me elaborar um pouco mais: minha leitura do FPS é armazenada como um bóia, pois os quadros/segundos geralmente acabam não sendo um bom número. Portanto, meu número pode ter 60, ou pode ser 59.12345. 60 precisariam apenas de 2 bytes e 59.12345 precisariam de 8 (1 para o período). Então eu pensei "oh ok, eu preciso contar a quantidade de dígitos que tem, sem problemas!" Rapaz, eu estava em choque.

Fiz um método para contar os dígitos, contando o lado esquerdo do lugar decimal foi fácil, apenas o primeiro o lançou como um INT para remover os pontos decimais e dividir por 10 (na verdade, acho que tive um pouco de troca de bits lá) e Conte a quantidade de vezes que posso fazer isso até chegar a 0. e agora para contar os dígitos no lado direito, bem, apenas multiplicarei por 10, subtrairei o dígito e farei isso até que ele atinja zero. O método geralmente retornaria 32, acho que era. Então, eu já dei e dei uma olhada nele em depuração, quando você multiplica o flutuador efetivamente movendo as colunas de dígitos por causa do problema de precisão bem conhecido que acabou de anexar outro dígito!

Fiz alguns grandes pesquisas no Google, mas não consegui encontrar nada acima de Char Str [128] e SCANF se em seguida, Strlen (STR) menos 1 (terminador nulo). Mas eu esperava uma solução mais elegante. No final, acabei de lançá -lo como um INT e permiti o suficiente para 9999 fps, também adicionei um cheque para ver se o FPS> 9999, mas acho que nunca vai acontecer. Melhor seguro do que falha seg :(

TLDR: Existe uma maneira de obter a quantidade de dígitos em uma bóia? Como o scanf faz isso?!

Desculpe por Long Post, só queria compartilhar minha frustração>: D

Editar: erros de ortografia

Foi útil?

Solução

Considerando que é C ++ sobre o qual estamos falando, por que não seguir o STL?

Precisão 5 locais após o ponto decimal, pode ser uma quantidade variável de caracteres:

std::stringstream ss;
ss << std::setprecision (5) << std::fixed << f; 
std::string fps = ss.str();

Precisão máxima 5 dígitos significativos:

std::stringstream ss;
ss << std::setprecision (5) << f; 
std::string fps = ss.str();

Outras dicas

Você pode truncar/forçar o número do ponto flutuante para qualquer precisão que desejar usando o Sprintf. Então o problema desaparece.

Como os números de pontos flutuantes não são armazenados de maneira precisa, não há realmente nenhuma maneira eficaz de contar o número de dígitos. O que você provavelmente deseja fazer é controlar o comprimento do número que o float fornece e usar um buffer com um tamanho fixo.

Com printf(), scanf() e funções relacionadas, o tamanho de um número de ponto flutuante pode ser especificado modificando o especificador do tipo de formato. Enquanto simples %f pode ser o mais comum, pode ser usado de maneira mais flexível, adicionando modificadores entre o % e a f, como:

%[width][.precision]f

Onde [width] refere-se a mínimo Número de dígitos a serem exibidos para o número (não haverá truncamento se ele for além) e [.precision] Especifica o número exato de dígitos a serem exibidos após o ponto decimal.

A título de exemplo, você pode examinar a saída do seguinte programa:

#include <cstdio>

using std::printf;
int main() {
  float f(59.12345);

  printf("[%f]\n", f);    // [59.123451]
  printf("[%15f]\n", f);  // [      59.123451]
  printf("[%1f]\n", f);   // [59.123451]
  printf("[%.2f]\n", f);  // [59.12]
  printf("[%6.2f]\n", f); // [ 59.12]
  printf("[%4.1f]\n", f); // [59.1]
}

O tamanho exato da matriz de caracteres ainda seria variável, dependendo do valor antes do decimal. Mas, desde que você possa controlar a largura e a precisão, alocar memória suficiente em uma matriz de caracteres (ou ajustar o número em uma matriz de comprimento fixo) deve ser substancialmente mais simples.

Nós iremos John em CashCommons Deu a resposta tradicional, basta usar os qualificadores de formato PrintF para forçar uma certa largura. Normalmente, acho que dois lugares decimais são suficientes para taxas de quadros. Ele permite distinguir entre 30 qps e 29,97 fps, os dois valores mais comuns.

 sprintf (buffer, "%.2f", fps);

Mas se você quiser saber qual seria o pior caso, há uma maneira de saber disso também. Confira http://en.wikipedia.org/wiki/ieee_754-2008.

Ele mostra que os valores de ponto flutuante (carros alegóricos de 32 bits) têm 24 dígitos binários na Mantissa, que dão certo para 7,225 dígitos decimais, chame -o 8. Adicione 5 dígitos para o expoente, 1 para o sinal, 1 para uma liderança 0, 1 para o ponto decimal e você fica

 1 + 1 + 8 + 5 = 15 characters

Adicione espaço para um NULL Terminante e você terá 16 dígitos.

São quadros por segundo. Basta usar três dígitos à esquerda e um à direita, quem se importa com o que a representação do ponto flutuante acha que existe abaixo do lugar dos décimos?

Edite em resposta ao primeiro comentário.

http://en.wikipedia.org/wiki/floating_point

Se realmente estamos depois do número de dígitos no flutuador, precisamos saber como os carros alegóricos funcionam. O valor exato representado no Datatype de Float Standard IEEE possui uma certa quantidade de bits geralmente 32 ou 64, que são alocados de uma maneira padronizada de fornecer uma quantidade definida de dígitos significativos e algum expoente de energia para escalar ou descer. 24 bits de dígitos significativos chegam a cerca de sete lugares em decimais. Sempre haverá alguma forma de truncamento ou erro de arredondamento no final do final (como um terço, escrito em decimal, sempre redondo quando você para de escrever os três repetidos).

Talvez seu número pare após sete ou oito dígitos, mas o erro de arredondamento da máquina o mantém por acidente? Não faz sentido ler esse tipo de dados.

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