Toon Krijthe'nin cevabı çoğu zaman işe yarıyor . Ancak bazen fazla sayıda kene üretecektir. Negatif sayılarla da çalışmaz. Soruna genel yaklaşım tamam ama bunu halletmenin daha iyi bir yolu var. Kullanmak istediğiniz algoritma, gerçekte ne elde etmek istediğinize bağlı olacaktır. Aşağıda JS Ploting kütüphanemde kullandığım kodu size sunuyorum. Test ettim ve her zaman işe yarıyor (umarım;)). İşte ana adımlar:
- global extremas xMin ve xMax elde edin (algoritmada yazdırmak istediğiniz tüm grafikleri dahil edin)
- xMin ve xMax arasındaki aralığı hesapla
- Aralığınızın büyüklük sırasını hesaplayın
- aralığı tik sayısı eksi bire bölerek tik boyutunu hesaplayın
- bu isteğe bağlıdır. Her zaman sıfır onay işareti yazdırmak istiyorsanız, pozitif ve negatif tiklerin sayısını hesaplamak için tik boyutunu kullanırsınız. Toplam tik sayısı, toplamı +1 olacaktır (sıfır tik)
- her zaman yazdırılmış sıfır onay işaretiniz varsa buna gerek yoktur. Alt ve üst sınırları hesaplayın, ancak grafiği ortalamayı unutmayın
Hadi başlayalım. İlk önce temel hesaplamalar
var range = Math.abs(xMax - xMin); //both can be negative
var rangeOrder = Math.floor(Math.log10(range)) - 1;
var power10 = Math.pow(10, rangeOrder);
var maxRound = (xMax > 0) ? Math.ceil(xMax / power10) : Math.floor(xMax / power10);
var minRound = (xMin < 0) ? Math.floor(xMin / power10) : Math.ceil(xMin / power10);
Grafikimin tüm verileri kapsayacağından% 100 emin olmak için minimum ve maksimum değerleri yuvarlıyorum. Negatif olsun ya da olmasın ve daha sonra 1'i çıkararak, aralığın kat log10'u için de çok önemlidir. Aksi takdirde, algoritmanız birden küçük sayılar için çalışmayacaktır.
var fullRange = Math.abs(maxRound - minRound);
var tickSize = Math.ceil(fullRange / (this.XTickCount - 1));
//You can set nice looking ticks if you want
//You can find exemplary method below
tickSize = this.NiceLookingTick(tickSize);
//Here you can write a method to determine if you need zero tick
//You can find exemplary method below
var isZeroNeeded = this.HasZeroTick(maxRound, minRound, tickSize);
7, 13, 17 vb. Kenelerden kaçınmak için "hoş görünümlü keneler" kullanıyorum. Burada kullandığım yöntem oldukça basit. Gerektiğinde zeroTick'e sahip olmak da güzel. Konu bu şekilde çok daha profesyonel görünüyor. Tüm yöntemleri bu cevabın sonunda bulacaksınız.
Şimdi üst ve alt sınırları hesaplamanız gerekiyor. Sıfır tıklama ile bu çok kolaydır, ancak diğer durumda biraz daha fazla çaba gerektirir. Neden? Çünkü arsayı üst ve alt sınırların içinde güzelce ortalamak istiyoruz. Koduma bir bak. Değişkenlerden bazıları bu kapsamın dışında tanımlanmıştır ve bazıları da sunulan kodun tamamının tutulduğu bir nesnenin özellikleridir.
if (isZeroNeeded) {
var positiveTicksCount = 0;
var negativeTickCount = 0;
if (maxRound != 0) {
positiveTicksCount = Math.ceil(maxRound / tickSize);
XUpperBound = tickSize * positiveTicksCount * power10;
}
if (minRound != 0) {
negativeTickCount = Math.floor(minRound / tickSize);
XLowerBound = tickSize * negativeTickCount * power10;
}
XTickRange = tickSize * power10;
this.XTickCount = positiveTicksCount - negativeTickCount + 1;
}
else {
var delta = (tickSize * (this.XTickCount - 1) - fullRange) / 2.0;
if (delta % 1 == 0) {
XUpperBound = maxRound + delta;
XLowerBound = minRound - delta;
}
else {
XUpperBound = maxRound + Math.ceil(delta);
XLowerBound = minRound - Math.floor(delta);
}
XTickRange = tickSize * power10;
XUpperBound = XUpperBound * power10;
XLowerBound = XLowerBound * power10;
}
Ve işte daha önce bahsettiğim, kendiniz yazabileceğiniz ama benimkini de kullanabileceğiniz yöntemler
this.NiceLookingTick = function (tickSize) {
var NiceArray = [1, 2, 2.5, 3, 4, 5, 10];
var tickOrder = Math.floor(Math.log10(tickSize));
var power10 = Math.pow(10, tickOrder);
tickSize = tickSize / power10;
var niceTick;
var minDistance = 10;
var index = 0;
for (var i = 0; i < NiceArray.length; i++) {
var dist = Math.abs(NiceArray[i] - tickSize);
if (dist < minDistance) {
minDistance = dist;
index = i;
}
}
return NiceArray[index] * power10;
}
this.HasZeroTick = function (maxRound, minRound, tickSize) {
if (maxRound * minRound < 0)
{
return true;
}
else if (Math.abs(maxRound) < tickSize || Math.round(minRound) < tickSize) {
return true;
}
else {
return false;
}
}
Burada yer almayan tek bir şey daha var. Bu "güzel görünen sınırlar" dır. Bunlar, "güzel görünümlü işaretler" deki sayılara benzer sayılar olan alt sınırlardır. Örneğin, aynı tik boyutu ile 6'da başlayan bir grafiğe sahip olmaktansa, 5 tik boyutu 5 ile başlayan alt sınıra sahip olmak daha iyidir. Ama bu benim kovulmamı sana bırakıyorum.
Umarım yardımcı olur. Şerefe!