比例数是< = 255?

时间:2009-10-11 02:58:44

标签: java language-agnostic math distribution

我的单元格的数值可以是介于0和Integer.MAX_VALUE之间的任何值。我想相应地对这些单元格进行颜色编码。

如果值= 0,那么r = 0.如果值为Integer.MAX_VALUE,那么r = 255.但是它们之间的值怎么样?

我想我需要一个限制为x =>的函数。 Integer.MAX_VALUE是255.这是什么功能?或者有更好的方法吗?

我可以做(value / (Integer.MAX_VALUE / 255)),但这会导致许多低值为零。所以也许我应该用日志功能来做。

我的大多数值都在[0,10,000]范围内。所以我想强调那里的差异。

13 个答案:

答案 0 :(得分:16)

“最公平”的线性缩放实际上是这样完成的:

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

请注意,这只是伪代码并假定浮点计算。

如果我们假设Integer.MAX_VALUE + 1是2 ^ 31,那个/将给我们整数除法,那么它简化为

value / 8388608

为什么其他答案错误

一些答案​​(以及问题本身)提出了(255 * value / Integer.MAX_VALUE)的变体。据推测,必须使用round()floor()将其转换为整数。

如果使用floor(),则产生255的唯一value是Integer.MAX_VALUE本身。这种分布是不均衡的。

如果使用round(),则每次击中0和255的次数将是1-254的一半。也不平衡。

使用上面提到的缩放方法,不会出现这样的问题。

非线性方法

如果您想使用日志,请尝试以下方法:

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

您也可以只取值的平方根(这不会一直到255,但如果您愿意,可以将其缩放)。

答案 1 :(得分:5)

我认为日志适合对此有好处,但看结果,我不太确定。

但是,Wolfram|Alpha非常适合experimenting with this sort of thing

我从那开始,结束了:

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

有趣的是,事实证明,这给Artelius的答案提供了几乎相同的结果:

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

恕我直言,你最好使用0-10000和10000-2 ^ 31的分割功能。

答案 2 :(得分: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,我的高中代数老师Buckenmeyer夫人会晕倒! 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)
巴克迈尔太太,你的努力并没有完全浪费掉!

答案 3 :(得分:2)

一般情况下(因为我不清楚这是一个Java还是语言不可知的问题),你可以将的值除以 Integer.MAX_VALUE,乘以{{1}并转换为整数。

答案 4 :(得分:2)

这个有效! r= value /8421504;

8421504实际上是'魔术'数字,等于MAX_VALUE / 255。因此,MAX_VALUE / 8421504 = 255(有些变化,但足够小的整数数学将摆脱它。

如果你想要一个没有幻数的人,这应该有效(并且性能相同,因为任何好的编译器都会用实际值代替它:

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

好的部分是,这不需要任何浮点值。

答案 5 :(得分:1)

您要查找的值是:r = 255 *(value / Integer.MAX_VALUE)。所以你必须把它变成一个double,然后再转换成int。

答案 6 :(得分:1)

请注意,如果您想要更亮更明亮,那么光度不是线性的,因此从值到颜色的直接映射不会产生良好的效果。

Color类有一种方法可以使颜色更亮。看看那个。

答案 7 :(得分:1)

大多数答案都讨论了线性实现,Artelius的回答似乎是最好的。但最好的公式将取决于您想要实现的目标以及您的价值观的分配。不知道很难给出理想的答案。

但只是为了说明,其中任何一个都可能是最适合你的:

  • 线性分布,每个映射到整个范围的1/265的范围。
  • 对数分布(倾向于低值),这将突出较低幅度的差异并减少较高幅度的差异
  • 反向对数分布(偏向高值),这将突出较高幅度的差异,并减少较低幅度的差异。
  • 颜色发生率的正态分布,其中每种颜色与其他颜色的出现次数相同。

同样,你需要确定你想要实现的目标。数据将用于什么。如果你的任务是建立这个,那么我强烈建议你澄清它,以确保它尽可能有用 - 并避免以后重新开发。

答案 8 :(得分:1)

问自己一个问题,“应该映射到128的值是多少?” 如果答案是大约十亿(我怀疑它是),那么使用线性。 如果答案在10-100万的范围内,则考虑平方根或日志。

另一个答案暗示了这一点(我无法发表评论或投票)。我同意。

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

答案 9 :(得分:1)

以下是一组用于在C#中使用扩展方法进行缩放,规范化,排名等数字的算法,尽管您可以将它们调整为其他语言:

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

有解释和图形可以解释您何时可能想要使用某种方法。

答案 10 :(得分:0)

最佳答案实际上取决于您想要的行为。

如果您希望每个单元格的颜色通常与邻居不同,请使用第二段中的 akf 并使用模数(x%256)。

如果您希望颜色与实际值有一些关系(例如“蓝色表示较小的值”,一直到“红色表示巨大的值”),您必须发布一些关于您预期的值分布的信息。既然你担心许多低值为零我可能会猜到你有很多这些值,但这只是猜测。

在第二种情况下,您确实希望将可能的响应分配到256“百分位数”并为每个响应分配一种颜色(每个百分位数中可能的响应数量相等)。

答案 11 :(得分:0)

如果您抱怨低数字变为零,那么您可能希望将值标准化为255而不是整个值范围。

公式将成为:

currentValue /(集合的最大值)

答案 12 :(得分:-1)

  

我可以这样做(值/(Integer.MAX_VALUE / 255))但这将导致许多低值为零。

您可以采用的一种方法是使用模运算符(r = value%256;)。 虽然这不能确保Integer.MAX_VALUE结果为255,但它可以保证0到255之间的数字。它还允许在0-255范围内分配低数字。

编辑:

有趣的是,当我对此进行测试时,Integer.MAX_VALUE % 256会导致255(我最初错误地对%255进行了测试,这导致了错误的结果)。这似乎是一个非常直接的解决方案。