我的单元格的数值可以是介于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]范围内。所以我想强调那里的差异。
答案 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的回答似乎是最好的。但最好的公式将取决于您想要实现的目标以及您的价值观的分配。不知道很难给出理想的答案。
但只是为了说明,其中任何一个都可能是最适合你的:
同样,你需要确定你想要实现的目标。数据将用于什么。如果你的任务是建立这个,那么我强烈建议你澄清它,以确保它尽可能有用 - 并避免以后重新开发。
答案 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;
)。 虽然这不能确保但它可以保证0到255之间的数字。它还允许在0-255范围内分配低数字。 Integer.MAX_VALUE
结果为255,
编辑:
有趣的是,当我对此进行测试时,Integer.MAX_VALUE % 256
会导致255
(我最初错误地对%255
进行了测试,这导致了错误的结果)。这似乎是一个非常直接的解决方案。