This class is designed to determine the language of a text; the user has to enter 4 text in english, danish, italian and latin, and then the text whose language he wants to determine. The console says
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at Riconoscimento2.creaTabellaTotale(Riconoscimento2.java:365) at Riconoscimento2.main(Riconoscimento2.java:25)
I use eclipse, in Run Configurations – Arguments I wrote -Xms2g-Xmx3g. I don’t understand where is the problem.
The code is
import java.io.*; import java.util.*; import prog.io.*; public class Riconoscimento2 { public static void main(String[] args) { char[] array = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ' '}; System.out.println("Immetti l'intero n per il calcolo degli n-grammi "); // questa istruzione richiede di immettere l'intero n BufferedReader sc = new BufferedReader(new InputStreamReader(System.in)); Scanner in = new Scanner(System.in); int n = in.nextInt(); StringBuffer[] tabellaTotale = creaTabellaTotale(n, array); System.out.println("Immetti un testo in inglese, che poi verrà utilizzato come paradigma. Ricordati di non inserire rientri a capo."); // con questa e le successive istruzioni si chiede di immettere dei testi campioni scritti in inglese, danese, italiano, latino String testo_inglese =""; try{ testo_inglese = sc.readLine(); }catch(IOException e1){ System.out.println("Input non corretto. Immetti un testo in inglese. "); } System.out.println("Immetti un testo in danese, che poi verrà utilizzato come paradigma. Ricordati di non inserire rientri a capo."); String testo_danese =""; try{ testo_danese = sc.readLine(); }catch(IOException e1){ System.out.println("Input non corretto. Immetti un testo in danese. "); } System.out.println("Immetti un testo in italiano, che poi verrà utilizzato come paradigma. Ricordati di non inserire rientri a capo."); String testo_italiano =""; try{ testo_italiano = sc.readLine(); }catch(IOException e1){ System.out.println("Input non corretto. Immetti un testo in italiano. "); } System.out.println("Immetti un testo in latino, che poi verrà utilizzato come paradigma. Ricordati di non inserire rientri a capo."); String testo_latino =""; try{ testo_latino = sc.readLine(); }catch(IOException e1){ System.out.println("Input non corretto. Immetti un testo in latino. "); } System.out.println("Immetti il testo di cui vuoi determinare la lingua. Ricordati di non inserire rientri a capo."); String testo =""; try{ testo = sc.readLine(); }catch(IOException e1){ System.out.println("Input non corretto. Immetti il testo di cui vuoi determinare la lingua. "); } StringBuffer testo_inglese_formattato = formatta(testo_inglese); // testo_inglese_formattato rappresenta il testo inglese immesso dall'utente in cui i caratteri non alfabetici sono stati trasformati in spazi // e sono stati rimossi gli spazi multipli. Lo stesso discorso vale per le righe successive. StringBuffer testo_danese_formattato = formatta(testo_danese); StringBuffer testo_italiano_formattato = formatta(testo_italiano); StringBuffer testo_latino_formattato = formatta(testo_latino); StringBuffer testo_formattato = formatta(testo); if ( n > testo.length() ) // questo controllo serve per gestire il caso in cui l'intero immesso dall'utente è più lungo della lunghezza del testo System.out.println("Hai immesso un intero troppo grande se confrontato al testo"); else { int[] lista_testo = creaLista(testo_formattato, tabellaTotale, n) ; // questa istruzione crea la sequenza delle occorrenze degli n-grammi presenti nel testo immesso dall'utente e poi formattato int[] lista_inglese = creaLista(testo_inglese_formattato, tabellaTotale, n) ; int[] lista_danese = creaLista(testo_danese_formattato, tabellaTotale, n) ; int[] lista_italiano = creaLista(testo_italiano_formattato, tabellaTotale, n ); int[] lista_latino = creaLista(testo_latino_formattato, tabellaTotale, n) ; double scarto_inglese = calcolaScarto(tabellaTotale, testo_formattato, testo_inglese_formattato, n); double scarto_danese = calcolaScarto( tabellaTotale, testo_formattato, testo_danese_formattato, n); double scarto_italiano = calcolaScarto(tabellaTotale, testo_formattato, testo_italiano_formattato, n); double scarto_latino = calcolaScarto(tabellaTotale, testo_formattato, testo_latino_formattato, n); double[] v = {scarto_inglese, scarto_danese, scarto_italiano, scarto_latino}; double min = v[0]; for (int j =0; j<4; j++){ // una volta calcolati gli scarti, si determina lo scarto minimo; il programma if ( v[j]<min ) // comunicherà poi all'utente che la lingua del testo è quella che ha dato lo scarto minimo. min = v[j]; // Chiaramente si tratta di un procedimento probabilistico, tanto più efficiente quanto più i testi forniti sono lunghi. } String lingua = "italiano"; if ( min == v[0]) lingua = "inglese"; if ( min == v[1]) lingua = "danese"; if ( min == v[2]) lingua = "italiano"; if ( min == v[3]) lingua = "latino"; System.out.println("E' molto probabile che il testo inserito sia scritto in " + lingua); } in.close(); } public static StringBuffer formatta (String s){ // questo metodo serve per formattare il testo, trasformando i caratteri non alfabetici in spazi // ed eliminando gli spazi multipli s = s.toLowerCase(); StringBuffer b = new StringBuffer(); int m = s.length(); int conta_spazi = 0; StringBuffer h = new StringBuffer(s); for (int i = 0; i < m ; i++ ){ switch(h.charAt(i)) { case 'a': break; case 'A': break; case 'b': break; case 'B': break; case 'c': break; case 'C': break; case 'd': break; case 'D': break; case 'e': break; case 'E': break; case 'f': break; case 'F': break; case 'g': break; case 'G': break; case 'h': break; case 'H': break; case 'i': break; case 'I': break; case 'j': break; case 'J': break; case 'k': break; case 'K': break; case 'l': break; case 'L': break; case 'm': break; case 'M': break; case 'n': break; case 'N': break; case 'o': break; case 'O': break; case 'p': break; case 'P': break; case 'q': break; case 'Q': break; case 'r': break; case 'R': break; case 's': break; case 'S': break; case 't': break; case 'T': break; case 'u': break; case 'U': break; case 'v': break; case 'V': break; case 'w': break; case 'W': break; case 'x': break; case 'X': break; case 'y': break; case 'Y': break; case 'z': break; case 'Z': break; default: h.setCharAt(i, ' '); } } for (int i = 0; i < m ; i++ ){ if ( h.charAt(i) == ' ' ) conta_spazi++; else conta_spazi = 0; if ( conta_spazi <= 1) b = b.append(h.charAt(i)); } return b; } public static int[] creaLista (StringBuffer str , StringBuffer[] tabella, int n){ int[] tavolaOccorrenze = new int[pow(27,n)]; for(int i =0; i < pow(27, n); i++ ) tavolaOccorrenze[i] = numeroOccorrenze(str, tabella[i]); return tavolaOccorrenze; } public static double calcolaFrequenza( int[] tavolaOccorrenze, StringBuffer testo, String st, int n){ double tot = 0; for(int i =0; i < pow(27, n); i++ ) tot += tavolaOccorrenze[i]; double frequenza = 0; double occorrenze_st = numeroOccorrenze(testo, new StringBuffer(st)); return occorrenze_st / tot; } public static double calcolaScarto (StringBuffer[] tabella, StringBuffer testo1, StringBuffer testo2, int n){ double scarto = 0; int[] tavolaOccorrenze1 = creaLista(testo1, tabella, n); int[] tavolaOccorrenze2 = creaLista(testo2, tabella, n); for(int i =0; i < pow(27, n); i++ ) scarto += Math.pow(calcolaFrequenza(tavolaOccorrenze1, testo1, tabella[i].toString(), n)-calcolaFrequenza(tavolaOccorrenze2, testo2, tabella[i].toString(), n), 2); return scarto; } public static StringBuffer[] creaTabellaTotale(int n, char[] a) { /* questa funzione crea la tabella che definisce l'ordine degli n-grammi*/ StringBuffer[] tabella = new StringBuffer[ pow(27, n)]; for(int h = 1; h <= n ; h++){ for(int u =0; u < pow ( 27, h-1); u++){ for (int j = 0; j<27; j++){ for( int x =pow(27, n-h+1)*u + pow(27, n-h)*j; x< pow(27, n-h+1)*u + pow(27, n-h)*(j+1); x++) tabella[x] = tabella[x].append(a[j]); } } } return tabella; } public static int pow(int a, int b){ int tot = 1; for(int i =0; i<b ; i++) tot = a * tot ; return tot; } public static int numeroOccorrenze ( StringBuffer testo, StringBuffer parola){ int tot =0; if(parola.length() > testo.length()) System.out.println("L' n-gramma da cercare è troppo lungo in confronto al testo inserito "); else{ int n = parola.length(); for(int i = 0; i <= testo.length() - n; i++ ){ if(testo.substring(i,i+n) == parola.toString()) ++tot; } } return tot; } }
Advertisement
Answer
This line throws the exception:
StringBuffer[] tabella = new StringBuffer[pow(27, n)];
why? well, your function pow(a, b)
is correct but the n
variable is a bit off. You are reading it from there:
n = in.read();
This will give you the ascii code of the character you enter in the console, and not the number. If you write “1”, then n
will be 49, and pow(27, 49) is way too much.
To simply read the input of the user, you should try to use java.util.Scanner
instead, to get the number that the user inputs.