Подтвердить что ты не робот

Число шкал должно быть <= 255?

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

Если value = 0, то r = 0. Если значение Integer.MAX_VALUE, то r = 255. Но как насчет значений между?

Я думаю, мне нужна функция, предел которой при x = > Integer.MAX_VALUE равен 255. Что это за функция? Или есть лучший способ сделать это?

Я мог бы просто сделать (value / (Integer.MAX_VALUE / 255)), но это приведет к тому, что многие низкие значения будут равны нулю. Поэтому, возможно, я должен сделать это с помощью функции журнала.

Большинство моих значений будут находиться в диапазоне [0, 10000]. Поэтому я хочу выделить там различия.

4b9b3361

Ответ 1

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

Однако Wolfram | Alpha отлично подходит для экспериментирования с такими типами вещь:

Я начал с этого и закончил с:

r(x) = floor(((11.5553 * log(14.4266 * (x + 1.0))) - 30.8419) / 0.9687)

Интересно, что получается, что это дает почти одинаковые результаты Артелиусу ответ:

r(x) = floor(255 * log(x + 1) / log(2^31 + 1)

IMHO, вам лучше всего воспользоваться функцией split для 0-10000 и 10000-2 ^ 31.

Ответ 2

"Самое справедливое" линейное масштабирование выполняется следующим образом:

floor(256 * value / (Integer.MAX_VALUE + 1))

Обратите внимание, что это просто псевдокод и предполагает вычисления с плавающей запятой.

Если предположить, что Integer.MAX_VALUE + 1 равен 2 ^ 31, и что/даст нам целочисленное деление, то оно упростится до

value / 8388608

Почему другие ответы неверны

Некоторые ответы (а также сам вопрос) предложили вариант (255 * value / Integer.MAX_VALUE). Предположительно, это нужно преобразовать в целое число, используя round() или floor().

При использовании floor(), только value, который производит 255, является Integer.MAX_VALUE. Это распределение неравномерно.

Если использовать round(), то 0 и 255 будут попадать в полтора раза больше, чем 1-254. Также неравномерно.

Используя метод масштабирования, о котором я упоминал выше, такой проблемы не возникает.

Нелинейные методы

Если вы хотите использовать журналы, попробуйте следующее:

255 * log(value + 1) / log(Integer.MAX_VALUE + 1)

Вы также можете просто взять квадратный корень из значения (это не будет полностью до 255, но вы можете масштабировать его, если хотите).

Ответ 3

Для линейного отображения диапазона 0-2 ^ 32 до 0-255 просто возьмите старший байт. Вот как это выглядело бы с помощью двоичного & и смещения бит:

r = value & 0xff000000 >> 24

Использование mod 256 обязательно вернет значение 0-255, но вы не сможете нарисовать какой-либо смысл группировки из результатов - 1, 257, 513, 1025 будут отображаться в масштабе 1, даже если они далеки друг от друга.

Если вы хотите быть более дискриминационным среди низких значений и объединить еще много больших значений, тогда будет выполняться выражение журнала:

r = log(value)/log(pow(2,32))*256

РЕДАКТИРОВАТЬ: Yikes, учитель моей средней школы, миссис Бакенмайер упадет в обморок! log(pow(2,32)) совпадает с 32*log(2) и гораздо дешевле оценить. И теперь мы можем также учитывать это лучше, так как 256/32 является хорошим даже 8:

r = 8 * log(value)/log(2)

log(value)/log(2) на самом деле log-base-2 of value, который для нас очень аккуратно:

r = 8 * log(value,2)

Там, миссис Бакенмайер, ваши усилия не были полностью потрачены впустую!

Ответ 4

В общем (поскольку мне непонятно, является ли это вопросом Java или язык-Агностик), вы разделите значение, которое у вас есть на Integer.MAX_VALUE, умножьте на 255 и преобразуйте в целое число.

Ответ 5

Это работает! r= value /8421504;

8421504 на самом деле является "магическим" числом, которое равно MAX_VALUE/255. Таким образом, MAX_VALUE/8421504 = 255 (и некоторые изменения, но достаточно малая целочисленная математика, избавятся от него.

если вы хотите, чтобы в нем не было магических чисел, это должно работать (и иметь равную производительность, поскольку любой хороший компилятор заменит его фактическим значением:

r= value/ (Integer.MAX_VALUE/255);

Хорошая часть - это не потребует никаких значений с плавающей запятой.

Ответ 6

Значение, которое вы ищете: r = 255 * (значение/Integer.MAX_VALUE). Таким образом, вам придется превратить это в двойное, а затем вернуть обратно к int.

Ответ 7

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

Класс Color имеет способ сделать более яркий цвет. Посмотрите на это.

Ответ 8

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

Но чтобы проиллюстрировать, любой из них может быть лучшим для вас:

  • Линейное распределение, каждое отображение на диапазон, который составляет 1/266-й из общего диапазона.
  • Логарифмическое распределение (искаженное в сторону низких значений), которое выделит различия в более низких значениях и уменьшит различия в более высоких значениях
  • Реверсивное логарифмическое распределение (перекошенное к высоким значениям), которое будет выделять различия в более высоких величинах и уменьшать различия в более низких значениях.
  • Нормальное распределение частоты цветов, где каждый цвет отображается столько же раз, сколько и каждый другой цвет.

Опять же, вам нужно определить, чего вы пытаетесь достичь и для чего будут использоваться данные. Если вам было поручено построить это, я настоятельно рекомендую вам получить это разъяснение, чтобы убедиться, что оно является настолько полезным, насколько это возможно, - и чтобы не переделывать его позже.

Ответ 9

Задайте себе вопрос: "Какое значение должно отображаться на 128?" Если ответ составляет около миллиарда (я сомневаюсь, что это так), то используйте линейный. Если ответ находится в диапазоне 10-100 тысяч, то рассмотрите квадратный корень или журнал.

Другой ответ предложил это (я не могу комментировать или голосовать еще). Я согласен.

r = log (значение)/log (pow (2,32)) * 256

Ответ 10

Вот несколько алгоритмов для масштабирования, нормализации, ранжирования и т.д. с помощью методов расширения в С#, хотя вы можете адаптировать их к другим языкам:

http://www.redowlconsulting.com/Blog/post/2011/07/28/StatisticalTricksForLists.aspx

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

Ответ 11

Лучший ответ действительно зависит от поведения, которое вы хотите.

Если вы хотите, чтобы каждая ячейка просто имела цвет, отличный от соседа, перейдите к тому, что сказано в akf во втором абзаце, и используйте modulo (x% 256).

Если вы хотите, чтобы цвет имел некоторое отношение к фактическому значению (например, "синий означает меньшие значения", вплоть до "красного означает огромные значения" ), вам нужно было бы опубликовать что-то о вашем ожидаемом распределении значений. Поскольку вы беспокоитесь о том, что многие низкие значения равны нулю, я могу догадаться, что у вас их много, но это будет только предположение.

В этом втором сценарии вы действительно хотите распределить свои вероятные ответы в 256 "процентили" и назначить цвет каждому из них (где одинаковое количество вероятных ответов попадает в каждый процентиль).

Ответ 12

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

Формула будет следующей:

currentValue/(максимальное значение набора)

Ответ 13

Я мог бы просто сделать (значение/(Integer.MAX_VALUE/255)), но это приведет к тому, что многие низкие значения будут равны нулю.

Один подход, который вы могли бы предпринять, - использовать оператор modulo (r = value%256;). Хотя это не гарантирует, что Integer.MAX_VALUE окажется 255,, он будет гарантировать число от 0 до 255. Это также позволило бы распределять низкие числа в диапазоне 0-255.

EDIT:

Смешно, как я это проверю, Integer.MAX_VALUE % 256 приводит к 255 (я первоначально ошибочно протестировал против %255, что дало неправильные результаты). Это похоже на довольно прямое решение.