2010-07-21 7 views
10

Qual è il modo più efficiente per convertire l'importo numerico in ingleseAlgoritmo che converte l'importo numerico in inglese

ad es. Da 12 a 12 da 127 a centoventisette

+2

O in inglese cento ** e ** ventisette. :) –

+1

@Philip, il "e" è sbagliato se parli di inglese corretto. "E" è per le parti frazionarie. –

+1

@David - In inglese britannico, se un numero include un numero più piccolo ** e ** li unisce. Come nel 2010 - duemiladieci. Un'altra variazione è in valuta quando £ 1,20 è una sterlina venti o una sterlina e venti pence. Se sei annoiato puoi visualizzare http://www.english-at-home.com/speaking/saying-dates-and-numbers-in-english/ –

risposta

16

Non ci è voluto molto. Questa è un'implementazione scritta in Java.

http://snippets.dzone.com/posts/show/3685

Codice

public class IntToEnglish { 
    static String[] to_19 = { "zero", "one", "two", "three", "four", "five", "six", 
     "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", 
     "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" }; 
    static String[] tens = { "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"}; 
    static String[] denom = { "", 
     "thousand",  "million",   "billion",  "trillion",  "quadrillion", 
     "quintillion", "sextillion",  "septillion", "octillion",  "nonillion", 
     "decillion", "undecillion",  "duodecillion", "tredecillion", "quattuordecillion", 
     "sexdecillion", "septendecillion", "octodecillion", "novemdecillion", "vigintillion" }; 

    public static void main(String[] argv) throws Exception { 
     int tstValue = Integer.parseInt(argv[0]); 
     IntToEnglish itoe = new IntToEnglish(); 
     System.out.println(itoe.english_number(tstValue)); 
     /* for (int i = 0; i < 2147483647; i++) { 
      System.out.println(itoe.english_number(i)); 
     } */ 
    } 
    // convert a value < 100 to English. 
    private String convert_nn(int val) throws Exception { 
     if (val < 20) 
      return to_19[val]; 
     for (int v = 0; v < tens.length; v++) { 
      String dcap = tens[v]; 
      int dval = 20 + 10 * v; 
      if (dval + 10 > val) { 
       if ((val % 10) != 0) 
        return dcap + "-" + to_19[val % 10]; 
       return dcap; 
      }   
     } 
     throw new Exception("Should never get here, less than 100 failure"); 
    } 
    // convert a value < 1000 to english, special cased because it is the level that kicks 
    // off the < 100 special case. The rest are more general. This also allows you to 
    // get strings in the form of "forty-five hundred" if called directly. 
    private String convert_nnn(int val) throws Exception { 
     String word = ""; 
     int rem = val/100; 
     int mod = val % 100; 
     if (rem > 0) { 
      word = to_19[rem] + " hundred"; 
      if (mod > 0) { 
       word = word + " "; 
      } 
     } 
     if (mod > 0) { 
      word = word + convert_nn(mod); 
     } 
     return word; 
    } 
    public String english_number(int val) throws Exception { 
     if (val < 100) { 
      return convert_nn(val); 
     } 
     if (val < 1000) { 
      return convert_nnn(val); 
     } 
     for (int v = 0; v < denom.length; v++) { 
      int didx = v - 1; 
      int dval = new Double(Math.pow(1000, v)).intValue(); 
      if (dval > val) { 
       int mod = new Double(Math.pow(1000, didx)).intValue(); 
       int l = val/mod; 
       int r = val - (l * mod); 
       String ret = convert_nnn(l) + " " + denom[didx]; 
       if (r > 0) { 
        ret = ret + ", " + english_number(r); 
       } 
       return ret; 
      } 
     } 
     throw new Exception("Should never get here, bottomed out in english_number"); 
    } 
} 
2

Un modo per raggiungere questo obiettivo sarebbe quello di utilizzare guardare in alto tabelle. Sarebbe in qualche modo una forza bruta, ma facile da configurare. Ad esempio, potresti avere le parole per 0-99 in una tabella, quindi una tabella per decine, centinaia, migliaia, ecc. Alcuni semplici calcoli ti daranno l'indice della parola che ti serve da ogni tabella.

+0

Sarebbe un enorme spreco di memoria. – Christian

+0

Sono d'accordo con la tua valutazione, ma ho usato il termine "forza bruta" nella mia descrizione. Inoltre, esistono altre risposte per questa stessa domanda che utilizzano un approccio alla tabella di ricerca, compresa la risposta accettata. Non sono sicuro del motivo per cui il tuo commento si applica solo alla mia risposta. – nathan

1

.) Fare una biblioteca di tutti i numeri & posizioni (ad esempio 1 ha altra notazione di 10, un altro di 100, ecc) .) Fare un elenco di eccezioni (ad esempio per 12) ed essere consapevoli, che nel vostro algoritmo, la stessa eccezione è per 112, 1012 ecc.

se si desidera una velocità ancora maggiore, creare un numero memorizzato nella cache di numeri necessari.

1

Nota alcune regole:

  • Decine numeri (venti, trenta, etc.) che terminano in Y sono seguiti da trattini.
  • Gli anni sono speciali (tranne 15-19, ma sono ancora speciali).
  • Tutto il resto è solo una combinazione di digit place come "tremila".

È possibile ottenere il posto di un numero tramite la divisione piano di interi: 532/100 -> 5

2

Questo è un po 'vecchio codice python sul mio disco rigido. Ci potrebbe essere bug ma dovrebbe mostrare l'idea di base:

class Translator: 
    def transformInt(self, x): 
     translateNumbers(0,[str(x)]) 

    def threeDigitsNumber(self,number): 
     snumber=self.twoDigitsNumber(number/100) 
     if number/100!=0: 
      snumber+=" hundred " 
     snumber+self.twoDigitsNumber(number) 
     return snumber+self.twoDigitsNumber(number) 
    def twoDigitsNumber(self,number): 
     snumber="" 
     if number%100==10: 
      snumber+="ten" 
     elif number%100==11: 
      snumber+="eleven" 
     elif number%100==12: 
      snumber+="twelve" 
     elif number%100==13: 
      snumber+="thirteen" 
     elif number%100==14: 
      snumber+="fourteen" 
     elif number%100==15: 
      snumber+="fifteen" 
     elif number%100==16: 
      snumber+="sixteen" 
     elif number%100==17: 
      snumber+="seventeen" 
     elif number%100==18: 
      snumber+="eighteen" 
     elif number%100==19: 
      snumber+="nineteen" 
     else: 
      if (number%100)/10==2: 
       snumber+="twenty-" 
      elif (number%100)/10==3: 
       snumber+="thirty-" 
      elif (number%100)/10==4: 
       snumber+="forty-" 
      elif (number%100)/10==5: 
       snumber+="fifty-" 
      elif (number%100)/10==6: 
       snumber+="sixty-" 
      elif (number%100)/10==7: 
       snumber+="seventy-" 
      elif (number%100)/10==8: 
       snumber+="eighty-" 
      elif (number%100)/10==9: 
       snumber+="ninety-" 
      if (number%10)==1: 
       snumber+="one" 
      elif (number%10)==2: 
       snumber+="two" 
      elif (number%10)==3: 
       snumber+="three" 
      elif (number%10)==4: 
       snumber+="four" 
      elif (number%10)==5: 
       snumber+="five" 
      elif (number%10)==6: 
       snumber+="six" 
      elif (number%10)==7: 
       snumber+="seven" 
      elif (number%10)==8: 
       snumber+="eight" 
      elif (number%10)==9: 
       snumber+="nine" 
      elif (number%10)==0: 
       if snumber!="": 
        if snumber[len(snumber)-1]=="-": 
         snumber=snumber[0:len(snumber)-1] 
     return snumber 
    def translateNumbers(self,counter,words): 
     if counter+1<len(words): 
      self.translateNumbers(counter+1,words) 
     else: 
      if counter==len(words): 
       return True 
     k=0 
     while k<len(words[counter]): 
      if (not (ord(words[counter][k])>47 and ord(words[counter][k])<58)): 
       break 
      k+=1 
     if (k!=len(words[counter]) or k==0): 
      return 1 
     number=int(words[counter]) 
     from copy import copy 
     if number==0: 
      self.translateNumbers(counter+1,copy(words[0:counter]+["zero"]+words[counter+1:len(words)])) 
      self.next.append(copy(words[0:counter]+["zero"]+words[counter+1:len(words)])) 
      return 1 
     if number<10000: 
      self.translateNumbers(counter+1,copy(words[0:counter] 
                 +self.seperatewords(self.threeDigitsNumber(number)) 
                 +words[counter+1:len(words)])) 
      self.next.append(copy(words[0:counter] 
             +self.seperatewords(self.threeDigitsNumber(number)) 
             +words[counter+1:len(words)])) 
     if number>999: 
      snumber="" 
      if number>1000000000: 
       snumber+=self.threeDigitsNumber(number/1000000000)+" billion " 
       number=number%1000000000 
      if number>1000000: 
       snumber+=self.threeDigitsNumber(number/1000000)+" million " 
       number=number%1000000 
      if number>1000: 
       snumber+=self.threeDigitsNumber(number/1000)+" thousand " 
       number=number%1000 
      snumber+=self.threeDigitsNumber(number) 
      self.translateNumbers(counter+1,copy(words[0:counter]+self.seperatewords(snumber) 
                 +words[counter+1:len(words)])) 
      self.next.append(copy(words[0:counter]+self.seperatewords(snumber) 
             +words[counter+1:len(words)])) 
2

Questa soluzione non tenta di tenere conto di spazi finali, ma è abbastanza veloce.

typedef const char* cstring; 
using std::string; 
using std::endl; 
std::ostream& GetOnes(std::ostream &output, int onesValue) 
{ 
    cstring ones[] = { "zero", "one", "two", "three", "four", "five", "six", 
      "seven", "eight", "nine" }; 
    output << ones[onesValue]; 
    return output; 
} 

std::ostream& GetSubMagnitude(std::ostream &output, int subMagnitude) 
{ 
    cstring tens[] = { "zeroty", "ten", "twenty", "thirty", "fourty", "fifty", 
     "sixty", "seventy", "eighty", "ninety"}; 
    if (subMagnitude/100 != 0) 
    {  
     GetOnes(output, subMagnitude/100) << " hundred "; 
     GetSubMagnitude(output, subMagnitude - subMagnitude/100 * 100); 
    } 
    else 
    { 
     if (subMagnitude >= 20) 
     { 
      output << tens[subMagnitude/10] << " "; 
      GetOnes(output, subMagnitude - subMagnitude/10 * 10); 
     } 
     else if (subMagnitude >= 10) 
     { 
      cstring teens[] = { "ten", "eleven", "twelve", "thirteen", 
         "fourteen", "fifteen", "sixteen", "seventeen", 
         "eighteen", "nineteen" }; 
      output << teens[subMagnitude - 10] << " "; 
     } 
     else 
     { 
      GetOnes(output, subMagnitude) << " "; 
     } 
    } 
    return output; 
} 

std::ostream& GetLongNumber(std::ostream &output, double input) 
{ 
    cstring magnitudes[] = {"", "hundred", "thousand", "million", "billion", 
          "trillion"}; 
    double magnitudeTests[] = {1, 100.0, 1000.0, 1000000.0, 1000000000.0, 
          1000000000000.0 }; 
    int magTestIndex = 0; 
    while (floor(input/magnitudeTests[magTestIndex++]) != 0); 
    magTestIndex -= 2; 
    if (magTestIndex >= 0) 
    { 
     double subMagnitude = input/magnitudeTests[magTestIndex]; 
     GetSubMagnitude(output, (int)subMagnitude); 
     if (magTestIndex) { 
      output << magnitudes[magTestIndex] << " "; 
      double remainder = input - (floor(input/
         magnitudeTests[magTestIndex]) * 
         magnitudeTests[magTestIndex]); 
      if (floor(remainder) > 0) 
      { 
       GetLongNumber(output, remainder); 
      } 
     } 
    } 
    else 
    { 
     output << "zero"; 
    } 
    return output; 
} 
+0

Ovviamente, le dichiarazioni di non responsabilità includono che non rappresentano numeri superiori a 999,999,999,999,999, non fa frazioni e non gestisce numeri negativi. Abbastanza facile da aggiungere, ma devi fermarti ad un certo punto. –

2

Inizia risolvendo 1-99, con un elenco di numeri per 1-20, e poi 30, 40, ..., 90. Quindi aggiungere centinaia di ottenere 1-999. Quindi usa quella routine per dare il numero di ciascuna potenza di 1.000 per il massimo che vuoi (penso che la più alta nomenclatura standard sia per decillion, che è 10^33).

Un piccolo avvertimento è che è un po 'complicato ottenere gli spazi vuoti in tutti i casi se si sta tentando di iniziare e finire senza uno spazio in eccesso. La soluzione facile è mettere uno spazio vuoto dopo ogni parola e poi rimuovere lo spazio vuoto finale quando hai finito. Se si tenta di essere più precisi mentre si costruisce la stringa, è probabile che si finisca con spazi vuoti mancanti o spazi in eccesso.