2008-11-20 134 views

Respuesta

5

En primer lugar, es importante saber que los números de coma flotante son aproximados. Vea el enlace proporcionado por @Greg Hewgill para entender por qué este problema no se puede resolver por completo.

Pero aquí hay un par de soluciones al problema que probablemente satisfacer su necesidad:

Probablemente el mejor método, pero 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 

La manera más eficiente, pero probablemente 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); 
6

Realísticamente eso no es posible. No es una limitación de C++, sino simplemente la forma en que funciona el punto flotante. Para muchos valores no hay representaciones precisas, por lo que no puede simplemente truncar a una cantidad de dígitos.

Puede truncar al imprimir utilizando cadenas de formato de impresión.

Si realmente necesita almacenar solo un número limitado de dígitos, le sugiero que utilice un tipo de datos de precisión fija.

3

Creo que la pregunta que debe hacerse aquí es: ¿Por qué lo necesita truncado?

Si es para comparar valores, quizás debería considerar usar la prueba épsilon. (con un valor de tolerancia extra, en su caso, ya que parece ser mucho más grande que el épsilon generalmente aceptado).

Si solo desea imprimir como 0.6000, utilice los métodos que otros hayan sugerido.

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

Por ejemplo, en su caso está truncando tres dígitos (numDigits). Tendrá que utilizar:

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

(lo que probablemente almacenar el resultado de powf en alguna parte, ya se está usando dos veces.)

Debido a la forma en flotadores son normalmente almacenados en los ordenadores, no habría probablemente sean inexactitudes. Sin embargo, eso es lo que obtienes por usar flotadores.

1

Utilice esta:

floor(0.6000002*10000)/10000 
0

Aquí es una función mediante el asesoramiento en otras respuestas y un ejemplo de su 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); 
} 
0

Al igual que en otras respuestas, pero no debes olvidar que ronda , floor y trunc son diferentes por definición.Véase la definición y el ejemplo de salida de los siguientes:

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

En este caso tenemos que trucate con una precisión de 4 decimales y deshacerse de los decimales no significativos:

trunc(valueToTrunc*10000)/10000 

o

value = (double)((int)(valueToTrunc*10000))/(double)10000 
0

para C++ 11 puede utilizar std::round se define en la cabecera <cmath>:

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