C ++ tiene std::nextafter()
, que devuelve el siguiente valor representable después de un valor de punto flotante dado f . En mi caso, me gustaría permitir n bits de slop en los bits de mantisa inferiores, por lo que 3 bits de slop requerirían obtener el octavo valor siguiente después de cierto valor dado f . Podría llamar nextafter()
ocho veces, pero ¿hay una mejor manera de manejar esto?
Para la mayoría de los valores, podría pasar con la conversión del valor FP a uint_64
, agregando la tolerancia ( 1<<3
para 3 bits de pendiente) y luego volviendo a double
, gracias al diseño de IEEE 754. Sin embargo, eso se basa en el punto flotante IEEE 754 ( una buena suposición, pero tampoco sólida como una roca).
(Para el fondo, quiero usar esto para izar puntos de intersección de la superficie del rayo, que ocasionalmente se encuentran dentro de la superficie debido a la imprecisión de FP. Aquellos familiarizados con el punto flotante robusto entenderán por qué epsilon
es una solución terrible).
fuente
std::numeric_limits<T>::is_iec559
para verificar si se usa IEEE 754 y especializar la función en consecuencia.Respuestas:
Un enfoque ingenuo podría ser multiplicar por 8 la distancia entre un valor y el siguiente flotante representable, en lugar de llamar 8 veces
std::nextafter
Aquí hay algunas pruebas, pero depende de usted determinar si esto es adecuado para su caso de uso.
Editar
Como señaló Steve Hollash ,
x
puede ser tan grande quex + d == d
. Daniel Jour sugirió aprovecharfrexp
(yldexp
), pero en el siguiente intento, usaré un enfoque diferente para determinar la dirección.Tenga en cuenta que se supone que
std::numeric_limits<double>::has_infinity == true
, de lo contrario::lowest()
, y::max()
debe ser utilizado.Esos son algunos resultados
fuente
x+d
Sin embargo, como está escrito, no es lo que estás buscando. Si x es grande, entonces (x + d) == x. Pero me gusta la idea: calcule el valor igual al bit de orden más bajo con un exponente coincidente, escalado por la "pendiente", y luego agregado al valor original.nextafter
cómo pasar la "dirección".frexp
antes de esto yldexp
después debería funcionar, ¿no?frexp
en particular, puedo mover mundos. ¡Gracias!Hasta donde yo sé, no hay una función estándar para esto. Sin embargo, Boost te tiene cubierto: Mira
boost::math::float_advance
. Si estás usando esto para comparar dos flotadores, probablemente quieras en suboost::math::float_distance
lugar.fuente