Pergunta

O que é a maneira mais fácil para truncar uma variável float C ++ que tem um valor de 0,6000002 para um valor de 0,6000 e armazená-lo de volta na variável?

Foi útil?

Solução

Em primeiro lugar, é importante saber que números de ponto flutuante são aproximadas. Veja o link fornecido pelo @ Greg Hewgill para entender por que esse problema não é totalmente solucionáveis.

Mas aqui estão um par de soluções para o problema que provavelmente irá satisfazer suas necessidades:

Provavelmente o método melhor, mas menos eficiente:

char sz[64];
double lf = 0.600000002;
sprintf(sz, "%.4lf\n", lf); //sz contains 0.6000

double lf2 = atof(sz);

//lf == 0.600000002;
//lf2 == 0.6000

printf("%.4lf", lf2); //print 0.6000

A maneira mais eficiente, mas provavelmente menos precisa:

double lf = 0.600000002;
int iSigned = lf > 0? 1: -1;
unsigned int uiTemp = (lf*pow(10, 4)) * iSigned; //Note I'm using unsigned int so that I can increase the precision of the truncate
lf = (((double)uiTemp)/pow(10,4) * iSigned);

Outras dicas

Uma boa referência para por isso acontece pode ser encontrado em O que cada cientista computador deve saber sobre ponto flutuante aritmético por David Goldberg.

Na realidade isso não é possível. Não é a limitação a C ++, mas apenas a forma como obras de ponto flutuante. Para muitos valores não existem representações precisas, para que você não pode simplesmente truncar a um número de dígitos.

Você poderia truncar ao imprimir usando cadeias de formato printf.

Se você realmente precisa para ser capaz de armazenar apenas um número limitado de dígitos, eu sugiro que você use um tipo de dados de precisão fixa em seu lugar.

Acho que a pergunta que deve ser feita aqui é: Por que você precisar dele truncado?

Se a sua para a comparação entre os valores, talvez você deve considerar o uso do teste de epsilon. (Com um valor de tolerância extra, no seu caso, uma vez que parece ser muito maior do que a epsilon geralmente aceite).

Se você está apenas querendo imprimi-lo como 0,6000, utilize os métodos já foi sugerido.

roundf(myfloat * powf(10, numDigits)) / powf(10, numDigits);

Por exemplo, em seu caso, você está truncando três dígitos (numDigits). Você usaria:

roundf(0.6000002 * 1000) / 1000
// And thus:
roundf(600.0002) / 1000
600 / 1000
0.6

(Você provavelmente armazenar o resultado de algum lugar powf, desde que você está usando-o duas vezes.)

Devido à forma como flutuadores são normalmente armazenados em computadores, provavelmente seria imprecisões. Isso é o que você ganha usando carros alegóricos, no entanto.

Use esta:

floor(0.6000002*10000)/10000

Para C ++ 11 você pode usar std::round definido no <cmath> cabeçalho:

auto trunc_value = std::round(value_to_trunc * 10000) / 10000;

Aqui está uma função usando o conselho em outras respostas e um exemplo de seu uso:

#include <iostream>
#include <cmath>

static void Truncate(double& d, unsigned int numberOfDecimalsToKeep);

int main(int, char*[])
{

  double a = 1.23456789;
  unsigned int numDigits = 3;

  std::cout << a << std::endl;

  Truncate(a,3);

  std::cout << a << std::endl;

  return 0;
}

void Truncate(double& d, unsigned int numberOfDecimalsToKeep)
{
    d = roundf(d * powf(10, numberOfDecimalsToKeep)) / powf(10, numberOfDecimalsToKeep);
}

Semelhante a outras respostas, mas você não deve esquecer que redondo, chão e trunc são diferentes por definição. Veja o exemplo definição e saída do seguinte:

http://www.cplusplus.com/reference/cmath/trunc/

Neste caso precisamos trucate com uma precisão de 4 casas decimais e se livrar de decimais não significativos:

trunc(valueToTrunc*10000)/10000

ou

value = (double)((int)(valueToTrunc*10000))/(double)10000
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top