functions c infinity

functions - ¿Por qué es infinito=0x3f3f3f3f?



c1 functions (3)

En algunas situaciones, uno generalmente usa un valor entero suficientemente grande para representar el infinito. Usualmente uso el mayor entero positivo / negativo representable. Eso generalmente produce más código, ya que necesita verificar si uno de los operandos es infinito antes de virtualmente todas las operaciones aritméticas para evitar desbordamientos. A veces sería deseable tener aritmética de enteros saturados. Por esa razón, algunas personas usan valores más pequeños para el infinito, que se pueden agregar o multiplicar varias veces sin desbordamiento. Lo que me intriga es el hecho de que es extremadamente común ver (especialmente en competencias de programación):

const int INF = 0x3f3f3f3f;

¿Por qué es ese número especial? Su representación binaria es:

00111111001111110011111100111111

No veo ninguna propiedad especialmente interesante aquí. Veo que es fácil de escribir, pero si ese fuera el motivo, casi cualquier cosa haría (0x3e3e3e3e, 0x2f2f2f2f, etc.). Se puede agregar una vez sin desbordamiento, lo que permite:

a = min(INF, b + c);

Pero todas las demás constantes harían, entonces. Google solo me muestra muchos fragmentos de código que usan esa constante, pero no explicaciones ni comentarios.

¿Alguien puede verlo?


Encontré alguna evidencia sobre esto here ( contenido original en chino); la idea básica es que 0x7fffffff es problemático ya que es "la parte superior" del rango de entradas de 4 bytes firmados; por lo tanto, agregar cualquier cosa a los resultados en números negativos; 0x3f3f3f3f, en su lugar:

  • todavía es bastante grande (el mismo orden de magnitud de 0x7fffffff);
  • tiene mucho espacio para la cabeza; Si dice que el rango válido de enteros se limita a los números debajo de él, puede agregarle cualquier "número positivo válido" y aún así obtener un infinito (es decir, algo >=INF ). Incluso INF+INF no se desborda. Esto permite mantenerlo siempre bajo control:

    a+=b; if(a>INF) a=INF;

  • es una repetición de bytes iguales, lo que significa que puede fácilmente memset cosas para INF ;

  • también, como @ Jörg W Mittag notó anteriormente, tiene una bonita representación ASCII, que permite que ambos lo vean al vuelo mirando volcados de memoria y lo escriban directamente en la memoria.

Puedo o no ser uno de los primeros descubridores de 0x3f3f3f3f. Publiqué un artículo rumano al respecto en 2004 ( http://www.infoarena.ro/12-ponturi-pentru-programatorii-cc # 9), pero he estado usando este valor desde 2002 al menos para las competencias de programación.

Hay dos razones para ello:

  • 0x3f3f3f3f + 0x3f3f3f3f no desborda int32. Para ello algunos utilizan 100000000 (mil millones).
  • uno puede establecer una matriz de entradas al infinito haciendo memset(array, 0x3f, sizeof(array))

0x3f3f3f3f es la representación ASCII de la cadena ???? .

Krugle encuentra 48 instancias de esa constante en toda su base de datos. 46 de esas instancias están en un proyecto Java, donde se usa como una máscara de bits para la manipulación de algunos gráficos.

1 proyecto es un sistema operativo, donde se utiliza para representar un dispositivo ACPI desconocido.

1 proyecto es nuevamente una máscara de bits para gráficos Java.

Entonces, en todos los proyectos indexados por Krugle, se usa 47 veces debido a su patrón de bits, una vez debido a su interpretación ASCII, y no una sola vez como representación del infinito.