Функция от целых чисел до интервала с плавающей запятой [0,1] - PullRequest
0 голосов
/ 01 января 2011

Учитывая целое число, я хотел бы получить уникальное число с плавающей запятой в интервале [0,1].(этот номер будет использоваться как идентификатор).Проблема, которую я обнаружил со всеми функциями, о которых я думал, заключается в том, что они сталкиваются с дубликатами перед тем, как заканчиваются целочисленные значения.Например, если f(a:int):float = 0.a, то f(16000) = 0.16 и f(16001) = 0.16001.Но так как это с плавающей точкой, 0.16 и 0.16001 могут быть представлены одинаково.Другими словами, мне нужна функция, которая выдает не только уникальные числа, но и числа, которые представлены уникально (по крайней мере, для целочисленной области C ++).

Я знаю, что ответ зависит от размера целого числа и числа с плавающей запятойуказать в конкретной среде, но если вы можете привести пример для конкретных размеров, это все равно будет полезно.

Ответы [ 6 ]

8 голосов
/ 01 января 2011

Как заметил кто-то другой, вы можете просто привести int к float того же размера, чтобы получить уникальный float (с некоторой последующей фильтрацией для NaN и -0 и Inf).Однако это не будет соответствовать вашему требованию нахождения в [0,1].Фактически, вы можете использовать это отношение, чтобы показать, что в [0,1] недостаточно чисел с плавающей точкой для представления набора целых чисел.Если вы используете double, тогда мантисса достаточно велика для 32-битного целого числа, и должно быть достаточно выражения типа I / (double)INT_MAX (очевидно, если нужно, оставьте без знака).

5 голосов
/ 02 января 2011

Если 23 бита достаточно, вы можете построить число с плавающей точкой из int n следующим образом:

float f;
*((__int32*)&f) = (0x7E<<23) | (n & 0x7FFFFF); // exponent=0x7E-0x7F=-1, fraction=n

Он отобразит целые числа [0, 2 ^ 23-1] в числа с плавающей точкой [0.5, 1.0)согласно стандарту IEEE с плавающей запятой.

Если 23 бита недостаточно, у вас есть решение по ссылке, которую вы указали сами.Между прочим, есть и другие важные замечания: обязательно поймите все ограничения.

1 голос
/ 02 января 2011

Это похоже на проблему хеширования функций и строк.Учитывая, что размер точности с плавающей запятой меньше, чем поддерживаемый типом int, вы неизбежно столкнетесь с коллизиями.

Математически правильный путь заключается в следующем:

f(х) = 0, где х = 0;f (x) = 1 / x, где x> 0 и x

В противном случае вы пытаетесь вписать больше значений, чем можете, чтоневозможно.

В качестве альтернативы (так как вы имеете дело с графикой), если вы хотите обработать весь диапазон целых чисел, и вы могли бы жить с округлением 2 близких целых до одного и того же значения, вы можете разделитьзначение на 2 (или на 3 или на сколько вы хотите), чтобы уменьшить, чтобы соответствовать всему необходимому диапазону int.Деление на 2 удвоит поддерживаемый диапазон.

Таким образом, 16000 и 16001 получат 1/8000.

Я полагаю, это зависит от вашей ситуации, но вы не можете разместить 1 миллион человек на стадионе на 500 000 мест и ожидать, что у каждого будет уникальный номер места ... у вас будут столкновения.

1 голос
/ 01 января 2011

использовать 1/(float)n это хорошая функция для распределения, и если n равно нулю, установите ее в 0.

0 голосов
/ 02 января 2011

Когда целочисленное значение представлено 32 битами, а значение с плавающей запятой представлено 32 битами, то, очевидно, невозможно иметь каждое возможное целочисленное отображение в уникальное число с плавающей запятой.Простое решение состоит в том, чтобы использовать double для идентификатора или short для значения.

Ключ должен использовать тип с плавающей запятой, для которого значения и имеют больше битов, чем целочисленный тип.

0 голосов
/ 01 января 2011

Просто приведите целое число к числу с плавающей точкой, при условии, что они имеют одинаковый размер, для каждого целого числа будет создан уникальный тип числа с плавающей точкой.

int id = 16;    
float f_id = (float) id;

РЕДАКТИРОВАТЬ: я только что прочитал, что вы хотите, чтобы числав диапазоне [0, 1] - это значительно уменьшит число возможных идентификаторов, вероятно, лучше всего использовать целое число в качестве идентификатора, а не число с плавающей точкой, которое зависит от представления в памяти, как вы указали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...