我有一个绘制数据的图表,但图表组件选择了比例和刻度间隔的模糊数字。我正在尝试定义一个简单的算法来做到这一点。图表将水平绘制,中间为0,两个条形图一个向左延伸,另一个向右延伸。例如,假设要绘制的值是-60和75.我会显示类似下面的内容(对粗糙道歉)
-80 -60 -40 -20 0 20 40 60 80
<--------|--------->
所以我需要一种方法将最大数字四舍五入到最接近的10,100,1000等,以及一种决定时间间隔的方法。为了使0可见,滴答间隔必须分成舍入的数字而没有余数。
这是我到目前为止所拥有的。我知道这可能是一种更简单的数学“纯”方法。
//Find the max number rounded
double factor = 10d;
if (maxValue >= 1000)
factor = 1000d;
else if (maxValue >= 100)
factor = 100d;
var roundedMax = Convert.ToInt32(Math.Floor((maxValue.GetValueOrDefault() + factor) / factor) * factor);
if (roundedMax == 70 || roundedMax == 90)
roundedMax += 10;
else if (roundedMax == 700 || roundedMax == 900)
roundedMax += 100;
ViewModel.MaximumValue = roundedMax;
ViewModel.MinimumValue = roundedMax * -1;
//Work out the interval for tick marks
int interval;
var roundedMax = Convert.ToInt32(ViewModel.MaximumValue);
if (roundedMax <= 10)
interval = 2;
else if (roundedMax <= 20)
interval = 5;
else if (roundedMax <= 50)
interval = 10;
else if (roundedMax < 100)
interval = 20;
else if (roundedMax == 100)
interval = 25;
else if (roundedMax <= 200)
interval = 50;
else if (roundedMax <= 500)
interval = 100;
else if (roundedMax < 1000)
interval = 200;
else if (roundedMax == 1000)
interval = 250;
else if (roundedMax <= 2000)
interval = 500;
else
interval = 1000;
ViewModel.TickInterval = interval;
答案 0 :(得分:2)
(对C#一无所知),我认为一般方法可能如下。
首先,确定接近maxValue
的10的力量。这可以通过基数为10的对数来完成,类似这样(伪代码)
logMax = floor(log10(maxValue))
将10增加回此功率以获得小于maxValue
的最大功率10:
base = pow(10, logMax)
现在您要查找超出base
的{{1}}的最小乘数:
maxValue
如果您想避免在示例中使用特定值(例如70或90),则可以对roundedMax = ceil(maxValue / base) * base
进行一些手动更正。
现在你已经舍入了最大值。您可以采用相同的方式舍入最小值,或者更好地分别计算roundedMax
的最大值和最小值,并取最大值base
,然后将两者相对于同一base
。
在此之后您可以指定刻度。您可以想到许多算法,其中大部分都需要一些手动编码。基本方法可能如下:假设您想要大约10个分数。因此,“理想的”刻度距离将是
base
现在,您可以使用相同的方法将idealTick = (roundedMax - roundedMin)/10
舍入到最接近的幂10:
idealTick
(我使用idealTick = pow10(ceil(log10(idealTick)))
确保它是&lt; = 10个刻度线),现在ceil
是10的幂。
您现在可以对其进行微调,以实现2 * 10或10 * 10次幂:
idealTick
我希望这些想法很清楚。我没有测试代码,你可能想要对它进行更多的微调。