LINUX.ORG.RU

«уместить» uint64 в int, данные не важны

 ,


0

2

Суть в том что определенная библиотека работает только с обычными int.

Данные не важны потому что абстрактные «максимум» и «текущее значение», и эти абстрактные данные только в uint64.

Как лучше сделать. Делить uint64 на 2 пока не уместится в std::numeric_limits<int>::max()?

★★★★★

Последнее исправление: cetjs2 (всего исправлений: 2)
Ответ на: комментарий от i-rinat

round(sqrt(lowN)/2) так вроде ок, спасибо.

bhfq ★★★★★
() автор топика
Ответ на: комментарий от PPP328

нормализовать отрезок [абстрактный минимум, абстрактный максимум] -> [INT_MIN, INT_MAX]

anonymous
()

вообще от задачи зависит, где-то уместно сделать насыщение(clamping), где-то отбросить младшие биты

anonymous
()

а если данные действительно не важны, то почему не передавать всегда константу: 0/1/7/42/100500

anonymous
()
Ответ на: комментарий от anonymous

потому что абстрактное значение и такой же максимум меняются. Но для отображения скажем на графике (хотя дело не в графике) нужны цифры умещающиеся в int.

bhfq ★★★★★
() автор топика
Ответ на: комментарий от anonymous

а если данные действительно не важны, то почему важен результат?

anonymous
()
Ответ на: комментарий от bhfq

Если кратко - нормализируешь не к 0..1 а к твоему диапазону допустимых значений

На простом примере: У тебя значения от 0 до 100, ты их хочешь нормализовать к значениям от 5 до 20. Тогда ты виртуально растягиваешь ось своих исходных значений таким образом, чтобы ее минимум оказался на минимуме требуемой области, а максимум на максимуме:

|-------------------------------|
0                              100
    |------------|
    5            20

|-------------------------------|
0                              100
|-------------------------------|
5                              20

Все остальные значения мапятся на новую область возможных значений автоматически.

Например у тебя было число 50 изначальных «попугаев». При новом мапинге оно будет на середине допустимых значений, т.е:

20 - 5 = 15 всего значений
15 / 2 = 7.5 середина

Следовательно твои «виртуальные» 50 нормализуются к 7.5.

int32_t normalize(uint64_t val) {
    static const __int128 sourcerange  = (         UINT64_MAX - 0);
    static const __int128 allowedrange = ((int64_t)INT32_MAX - INT32_MIN);
    return (int32_t)(val * allowedrange / sourcerange + INT32_MIN);
}

Проверяем на граничных случаях:

printf("%d %d %d\n", normalize(0), normalize(UINT64_MAX / 2), normalize(UINT64_MAX));

-2147483648 -1 2147483647
PPP328 ★★★★★
()
Ответ на: комментарий от PPP328

Мда. Оба предложенных в теме варианта так и не подходят. Твой сабж же вообще __int128 такого на винде нет. Да и сделай normalize на рандомных значениях что умещаются в int. http://cpp.sh/6bllw

Все таки моя оригинальная задумка делить abst_maximum N раз пока тот не уместится в std::numeric_limits<int>::max(), а затем и abst_current делить такое же количество раз вполне рабочий вариант.

Хотя в математике наверное есть какое-то умное слово и простое решение для этого.

bhfq ★★★★★
() автор топика
Ответ на: комментарий от bhfq

Да и сделай normalize на рандомных значениях что умещаются в int. http://cpp.sh/6bllw

И что не так? Посмотри, во сколько раз отличается шкала uint64 и int32. Твои несколько сотен тысяч для этой шкалы меньше единицы.

такого на винде нет.

На винфак. Или пользуйся mingw вместо своего убожества.

Хотя в математике наверное есть какое-то умное слово и простое решение для этого.

Нормализация и масштабирование. Как раз то, что я показал

PPP328 ★★★★★
()
Ответ на: комментарий от i-rinat

Извлеки квадратный корень и подели на два.

А почему так можно? Во-первых, так ведь линейная функция преобразуется в квадратный корень, а во-вторых, что если у него, например, его abst_maximum на самом деле равен INT_MAX?

proud_anon ★★★★★
()
Ответ на: комментарий от bhfq

Ну, собственно, PPP328 и написал «математически». Можно перефразировать:

пусть limit = std::numeric_limits<int>::max()
тогда x / limit == abst_current / abst_maximum
значит x == (abst_current * limit) / abst_maximum


Только он учёл полный диапазон int, а не только от 0 до std::numeric_limits<int>::max(). Это, конечно, лучше с точки зрения потери точности, но только если допустимо ставить положительным значениям в соответствие отрицательные. А если недопустимо или допустима бо́льшая потеря точности, то в строке (abst_current * limit) / abst_maximum, limit достаточно привести к uint64_t, а результат преобразовать в int.

Без __int128 в любом случае можно обойтись, только кода будет больше.

proud_anon ★★★★★
()
Ответ на: комментарий от proud_anon

А почему так можно?

Там всё равно всё эмпирически. Никаких деталей о задаче ТС не предоставил, поэтому все гадают. Кому-то кажется нормальным просто отбросить 32 младших бита. Кому-то нет. Ты, например, поднял вопрос о значениях. До этого все считали, что они занимают все значащие биты 64-битного числа.

i-rinat ★★★★★
()
Ответ на: комментарий от bhfq

Твой сабж же вообще __int128 такого на винде нет.

Что значит «на винде нет»? Это вопрос вообще-то к компилятору. В mingw для винды такое вполне есть.

SZT ★★★★★
()

Не знаю уж как проще объяснить. Выглядит это как масштабирование.

https://i.imgur.com/XbyroS7.png (пропорции естественно не верные)

Так вот допустим что библиотека рисования этого графика проприетарная и туда лучше не лезть, умеет только int , и на 32 битной сборке он 32 битный. Так как цифры не нужны, а нужны только нарисованные линии логично что их можно масштабировать на этот int.

bhfq ★★★★★
() автор топика

Элитный (переводится как избранный) пятизвездочный тупняк.

anonymous
()
Ответ на: комментарий от bhfq

Сделай свой флоатинг поинт тогда. Зафигачь скажем 6 бит в экспоненту и 26 в мантиссу. Так сохранится порядок чисел u64->u32, и более-менее точное значение на низах. Как и с какого бока к интам привести сам уж догадаешься. На «неграфике» можно нарисовать логарифмические полосы, чтобы порядок понимать. Если точность мантиссы не критична, тебе и просто float может сойти, там ее уже 23-24 бита.

anonymous
()

Масштабируй или обрезай, в зависимости от того что тебе нужно и что делает библиотека. В чём вопрос-то?

slovazap ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.