ios math floating-point floating-accuracy floating-point-precision

ios - ¿Cómo ceder o cementar con seguridad un CGFloat a int?



math floating-point (3)

EDITAR - lee los comentarios por las razones por las cuales esta respuesta no es correcta :)

Lanzar un float a un int es un floorf implícito ie (int)5.9 es 5 . Si no te importa, entonces simplemente echa :)

Si desea redondear, simplemente lanzar el resultado de un ceilf - casting después del redondeo no debe introducir ningún error (o, si lo desea, agregar uno antes del lanzamiento, es decir, `(int) (5.9 + 1) ''es'' 6 ''- lo mismo que redondear).

Para redondear al más cercano, simplemente agregue 0.5 - (int)(5.9+0.5) es 6 pero (int)(5.4+0.5) es 5 . Aunque solo usaría roundf(5.9) :)

A menudo necesito CGFloat o CGFloat un CGFloat a un int , para el cálculo de un índice de matriz.

El problema que veo permanentemente con floorf(theCGFloat) o ceilf(theCGFloat) es que puede haber problemas con las imprecisiones de punto flotante.

Entonces, ¿qué CGFloat si mi CGFloat es 2.0f pero internamente se representa como 1.999999999999f o algo así? Hago floorf y obtengo 1.0f , que es un flotador de nuevo. Y, sin embargo, debo lanzar esta bestia a int, que puede presentar otro problema.

¿Existe una mejor práctica de cómo plantar o cementar un float en un int tal manera que algo como 2.0 nunca se derribara accidentalmente a 1 y algo como 2.0 nunca llegaría accidentalmente a 2 ?


Hay un par de conceptos erróneos en su pregunta.

¿Qué pasa si mi CGFloat es 2.0f pero internamente está representado como 1.999999999999f

no puede suceder; 2.0, como todos los enteros razonablemente pequeños, tiene una representación exacta en coma flotante. Si tu CGFloat es 2.0f , entonces realmente es 2.0.

algo como 2.0 nunca accidentalmente llegaría al límite de 2

El techo de 2.0 es 2; ¿Qué más podría ser?

Creo que la pregunta que realmente está haciendo es "supongamos que hago un cálculo que produce un resultado inexacto, que matemáticamente debería ser exactamente 2.0, pero en realidad es un poco menos; cuando aplico floor a ese valor, obtengo 1.0 en lugar de 2.0 ¿Cómo puedo prevenir esto?

Esa es en realidad una pregunta bastante sutil que no tiene una sola respuesta "correcta". ¿Cómo has calculado el valor de entrada? ¿Qué vas a hacer con el resultado?


Respuesta suplementaria Swift

Estoy agregando esto como una respuesta complementaria para aquellos que vienen aquí buscando cómo usar floor y ceil con un CGFloat (como yo lo hice).

var myCGFloat: CGFloat = 3.001 floor(myCGFloat) // 3.0 ceil(myCGFloat) // 4.0

Y si se necesita un Int , entonces se puede convertir a uno.

var myCGFloat: CGFloat = 3.001 Int(floor(myCGFloat)) // 3 Int(ceil(myCGFloat)) // 4

Actualizar

Ya no es necesario usar las funciones C floor y ceil . Puede usar la round() Swift round() con reglas de redondeo .

var myCGFloat: CGFloat = 3.001 myCGFloat.round(.down) // 3.0 myCGFloat.round(.up) // 4.0

Si no desea modificar las variables originales, utilice rounded() .

Notas

  • Funciona con arquitecturas de 32 y 64 bits.

Ver también

  • Cómo redondear CGFloat