2012-07-05 22 views
8
myInt = int(5 * myRandom()) 

myRandom() es un flotador generado aleatoriamente, que debería ser 0,2.¿Casting a los errores de coma flotante e interna?

Por lo tanto, esta afirmación debería ser de 1.

Mi pregunta: ¿es posible que debido a un error de coma flotante NO se evalúe a 1?

Por ejemplo, si debido a un error de punto flotante algo que debería ser 0,2 que podría ser MENOS que eso? IE, por ejemplo, considere las siguientes posibilidades: 3

int(5 * 0.2)    = 1 //case 1 normal 
int(5 * 0.2000000000000001) = 1 //case 2 slightly larger, its OK 
int(5 * 0.1999999999999999) = 0 //case 3 negative, is NOT OK, as int() floors it 

¿Es case3 incluso posible ?, con ,1999999999999999 ser el resultado de un error de punto flotante? Nunca he visto un épsilon negativo hasta el momento, solo el caso 2, cuando es un poco más grande, y eso está bien, como cuando se lanza a int(), que lo "nivela" con el resultado correcto. Sin embargo, con un épsilon negativo, el efecto 'flooring' hará que el resultado 0.9999999999999996 se evalúe a 0.

+0

No creo que sea posible, no. La multiplicación y el redondeo solo deberían prestar atención a la cantidad máxima de dígitos significativos posibles. – Ryan

+1

Si se genera aleatoriamente, ¿por qué "debería" ser 0.2? –

+0

Esto es C++, no C. No puede usar la sintaxis del constructor en C. –

Respuesta

3

Es imposible que myRandom devuelva .2 porque .2 no es representable como flotante o doble, suponiendo que su sistema objetivo está utilizando el estándar binario flotante IEEE 754, que es abrumadoramente el predeterminado.

Si myRandom() devuelve el número representable más cercano a .2, entonces myInt será 1, porque el número más cercano a .2 representable como un flotante es ligeramente mayor que .2 (es 0.20000000298023223876953125), y así es el más representable doble (0.20000000000000001110223024625156540423631668090820312).

En otros casos, esto no será cierto. Por ejemplo, el doble más cercano a .6 es 0.59999999999999997779553950749686919152736663818359375, por lo que myInt será 2, no 3.

+0

Me gusta su respuesta, pero es preocupante. El verdadero problema era si podía obtener un resultado determinista lanzando un float a un int; sin embargo, por lo que ha dicho sobre el 0.6, parece que no. Tendré que hacer un redondeo personalizado. –

1

Sí, es posible, al menos en lo que respecta al estándar C.

El valor 0.2 no se puede representar exactamente en un formato binario de coma flotante. El valor devuelto por myRandom() estará, por lo tanto, ligeramente por debajo o ligeramente por encima del valor matemático 0.2. El estándar C permite cualquiera de los resultados.

Ahora bien, puede ser que la semántica IEEE solo permita que el resultado sea ligeramente mayor que 0.2, pero el estándar C no requiere semántica IEEE. Y eso es suponiendo que el resultado se deriva lo más exactamente posible del valor 0.2. Si el valor se genera a partir de una serie de operaciones de coma flotante, cada una de las cuales puede presentar un pequeño error, podría ser fácilmente menor o mayor que 0.2.

+0

Como una adición, lanzando un flotante a una ronda internacional, por lo que si el valor es ligeramente mayor a 0.2, terminará con un producto ligeramente mayor que 1, que redondeará hacia abajo. – Wug

+0

Este es solo un ejemplo, myRandom() podría ser cualquier cosa de 0 a 1, pero 0.2 parecía un buen ejemplo para ilustrar la diferencia entre los resultados de 0 y 1. El problema real es sobre el determinismo, estaba buscando averiguar si se lanza un Floatpoint a un int, se obtendría un resultado determinista. Parece que no. –

1

No es un punto flotante error, es la forma en que funciona el punto flotante. Cualquier fracción que no sea 1/(potencia de 2) no se puede representar exactamente, y se redondeará hacia arriba o hacia abajo al número representable más cercano.

Puede corregir su código multiplicando por un pequeño epsilon mayor que uno antes de convertir a entero.

myInt = int(5 * myRandom() * 1.000000000000001) 

Ver What Every Computer Scientist Should Know About Floating-Point Arithmetic.

0

Es posible, dependiendo del número que elija. Para verificar un número específico, siempre puede imprimirlos con mucha precisión: printf ("% 1.50f", 0.2)

0

¿por qué no multiplicar su flotador por 5.0 y luego usa la función circular para redondearlo adecuadamente?

+0

Esta es una ilustración, estas no son las figuras reales. –

+0

La idea todavía funciona. –

Cuestiones relacionadas