¿Cómo soltar o pegar un CGFloat a int de manera segura?

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

El problema que ve permanentemente con floorf(theCGFloat) o ceilf(theCGFloat) es que puede haber problemas con inexactitudes 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 float de nuevo. Y, sin embargo, debo lanzar a esta bestia para que pueda presentar otro problema.

¿Existe una práctica recomendada de cómo colocar un suelo o un piso como float en un int modo que algo así como el 2.0 nunca caiga accidentalmente a 1 y algo así como el 2.0 nunca obtendría accidentalmente un máximo de 2 ?

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

¿Qué pasa si mi CGFloat es 2.0f pero internamente se representa como 1.999999999999f

no puede suceder 2.0, como todos los integers razonablemente pequeños, tiene una representación exacta en punto flotante. Si su CGFloat es 2.0f , entonces realmente es 2.0.

algo así como el 2.0 nunca obtendría accidentalmente un máximo de 2

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


Creo que la pregunta que realmente estás preguntando es "supongo 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 less, cuando aplico floor a ese valor, obtengo 1.0 en lugar de 2.0 – ¿Cómo prevengo esto? "

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

Respuesta suplementaria rápida

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 lanzar a uno.

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

Actualizar

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

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

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

Notas

  • Funciona con architectures de 32 y 64 bit.

Ver también

  • Cómo networkingondear CGFloat

EDITAR: lea los comentarios por las razones por las cuales esta respuesta no es correcta 🙂

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

Si quieres networkingondear, simplemente echa el resultado de un ceilf : el casting después del networkingondeo no debe introducir ningún error (o, si quieres, agrega uno antes de lanzar, es decir, `(int) (5.9 + 1) 'es' 6 '- lo mismo que networkingondear).

Para networkingondear 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) 🙂

Intereting Posts