Распечатать горизонтальную гистограмму для букв в файле. Как его масштабировать? Джава
Я хотел бы подсчитать количество букв в текстовом файле и нарисовать горизонтальную гистограмму. Тем не менее, самый длинный бар должен иметь длину 50
звезды. Это не проблема, когда у меня число меньше 50
, но как его масштабировать, чтобы у меня все было на гистограмме?
Я придумал эту формулу: 50 - 50 * histogram[i] / maxnum
где 50
максимальная длина стержня, histogram[i]
это число случаев i-th
буква в алфавите и maxnum
это число, представляющее количество наиболее распространенных букв в моем файле.
int[] histogram = new int[26];
String alphabeth = "abcdefghijklmnopqrstuvwxyz";
Вот как я строю гистограмму:
while((line = bfr.readLine()) != null){
for (int i =0;i< line.length();i++){
int index = alphabeth.indexOf(line.charAt(i));
if (index != -1)
histogram[index]++;
}
}
Я ищу maxval
:
int maxnum = histogram[0];
for (int p=1; p<histogram.length;p++){
if (maxnum < histogram[p]){
maxnum = histogram[p];
}
}
И вот как я это рисую:
for (int i=0; i<alphabeth.length(); i++){
System.out.print(alphabeth.charAt(i) + " ");
int count = histogram[i];
for (int k=0; k<50-50*histogram[i]/maxval; k++){
System.out.print("*");
}
}
Это правильно?
2 ответа
Я не вижу смысла в 50-50. Вы не можете просто удалить первые 50?
Является ли гистограмма [i] или maxval типа float или double? Это необходимо для того, чтобы деление не возвращало целочисленное значение.
Кстати: вы должны действительно использовать скобки в вашей формуле. И, возможно, было бы неплохо рассчитать количество звездочек для отдельной печати и сохранить их в отдельной переменной, а не вычислять в заголовке цикла for.
Проблема с вашей логикой 50 заключается в том, что она искажает внешний вид данных, когда символ встречается 50 раз, а все остальные - нет. Если вы используете процент, ваши данные будут иметь смысл в гистограмме независимо от количества вхождений одного символа. Ниже приведен код, который я использовал для создания базовой гистограммы, которая выводит количество звездочек в зависимости от процента
HashMap<Integer, Integer> alphabet = new HashMap<>();
double totalChars = 0;
for(int i = 0; i < 26; i++)
{
Random ran = new Random();
int x = ran.nextInt(500) + 1; //create some random amount of char occurrences
alphabet.put(i, x);
totalChars += alphabet.get(i); //get the total char count
}
System.out.println("Total Chars: " + totalChars);
for(int i = 0; i < 26; i++)
{
System.out.print(i + " [" + ((double)alphabet.get(i))/totalChars * 100 + "%]: ");
for(int j = 0; j < ((double)alphabet.get(i))/totalChars * 100; j++)
{
System.out.print("*");
}
System.out.println();
}
При каждом запуске программы генерируются случайные вхождения, поэтому вы можете увидеть, как историограмма ведет себя и выглядит в процентах.
Выход:
Total Chars: 6898.0
0 [6.494636126413453%]: *******
1 [2.7544215714699916%]: ***
2 [3.0878515511742535%]: ****
3 [3.1603363293708324%]: ****
4 [4.914467961728037%]: *****
5 [1.7396346767178894%]: **
6 [0.8408234270803132%]: *
7 [4.450565381269933%]: *****
8 [3.102348506813569%]: ****
9 [1.0872716729486807%]: **
10 [6.668599594085242%]: *******
11 [7.060017396346767%]: ********
12 [3.0878515511742535%]: ****
13 [5.131922296317773%]: ******
14 [1.348216874456364%]: **
15 [5.131922296317773%]: ******
16 [2.638445926355465%]: ***
17 [1.290229051899101%]: **
18 [3.4067845752391994%]: ****
19 [1.6526529428819947%]: **
20 [7.089011307625398%]: ********
21 [6.364163525659612%]: *******
22 [5.682806610611771%]: ******
23 [5.769788344447666%]: ******
24 [5.030443606842563%]: ******
25 [1.0147868947521022%]: **