Почему бесконечность = 0x3f3f3f3f3f?

в некоторых ситуациях обычно используется достаточно большое целое значение для представления бесконечности. Обычно я использую наибольшее представимое положительное / отрицательное целое число. Это обычно дает больше кода, так как вам нужно проверить, является ли один из операндов бесконечностью перед практически всеми арифметическими операциями, чтобы избежать переполнения. Иногда было бы желательно иметь насыщенную целочисленную арифметику. По этой причине, некоторые люди используют меньшие значения для бесконечности, которые могут быть добавлены или умножается несколько раз без переполнения. Что меня интригует, так это то, что это чрезвычайно распространено (особенно в соревнованиях по программированию):

const int INF = 0x3f3f3f3f;

почему этот номер особенный? Это двоичное представление:

00111111001111110011111100111111

Я не вижу здесь ничего особенно интересного. Я вижу, что это легко ввести, но если это было причиной, почти все, что угодно (0x3e3e3e3e, 0x2f2f2f2f и т. д.). Его можно добавить раз без переполнения, которое позволяет для:

a = min(INF, b + c);

но тогда подойдут все остальные константы. Googling показывает мне только много фрагментов кода, которые используют эту константу, но никаких объяснений или комментариев.

кто-нибудь может это заметить?

3 ответов


я нашел некоторые доказательства об этом здесь (оригинальный контент на китайском языке); основная идея заключается в том, что 0x7fffffffff проблематично, так как это уже "верхняя" часть диапазона 4-байтовых подписанных ints; поэтому добавление чего-либо к нему приводит к отрицательным числам; 0x3f3f3f3f, вместо этого:

  • по-прежнему довольно большой (тот же порядок величины 0x7fffffff);
  • есть много запас; если вы говорите, что допустимый диапазон целых чисел ограничен числа под ним, вы можете добавить любое "действительное положительное число" к нему и все равно получить бесконечное (т. е. что-то >=INF). Даже INF+INF не заливает. Это позволяет держать его всегда "под контролем":

    a+=b;
    if(a>INF)
        a=INF;
    
  • является повторением равных байтов, что означает, что вы можете легко memset вещи INF;

  • кроме того, как @Jörg W Mittag заметил выше, он имеет хорошее представление ASCII, что позволяет как обнаружить его на лету, глядя на дампы памяти, так и записать его непосредственно в память.

0x3f3f3f3f является ASCII-представлением строки ????.

Krugle находит 48 экземпляров этой константы во всей своей базе данных. 46 из этих экземпляров находятся в проекте Java, где он используется в качестве битовой маски для некоторых графических манипуляций.

1 проект-это операционная система, в которой он используется для представления неизвестного устройства ACPI.

1 проект снова является битовой маской для графики Java.

Итак, во всех проектах, индексированных Krugle, это используется 47 раз из-за его bitpattern, один раз из-за его интерпретации ASCII, а не один раз как представление бесконечности.


Я могу быть или не быть одним из самых ранних первооткрывателей 0x3f3f3f3f. Я опубликовал румынскую статью об этом в 2004 году (http://www.infoarena.ro/12-ponturi-pentru-programatorii-cc #9), но я использую это значение с 2002 года, по крайней мере, для соревнований по программированию.

есть две причины для этого:

  • 0x3f3f3f3f3f + 0x3f3f3f3f не переполняет int32. Для этого некоторые используют 100000000 (один миллиард).
  • можно установить массив ints до бесконечности, делая memset(array, 0x3f, sizeof(array))