/*
* [Italian.java]
*
* Summary: Display a number in Italian words.
*
* Copyright: (c) 1999-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
*
* Licence: This software may be copied and used freely for any purpose but military.
* http://mindprod.com/contact/nonmil.html
*
* Requires: JDK 1.8+
*
* Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
*
* Version History:
* 1.0 2009-01-21 initial version
* 1.1 2009-04-20 corrections fro Davide Vandelli
* 1.2 2009-05-02 correct spelling: milliardo to miliardo, milliardi to miliardi
*/
package com.mindprod.inwords;
import static java.lang.System.*;
/**
* Display a number in Italian words.
*
* e.g. -12,345 is meno dodicimilatrecentoquarantacinque
*
* 9,223,372,036,854,775,807 is
* novemiladuecentoventitre triliardi trecentosettantadue trilioni trentasei milliardi ottocentocinquantaquattro
* milioni settecentosettantacinquemilaottocentosette
*
* Italian is unusual in that is uses no spaces between the fragments, except in large numbers.
*
* For rules on how Italian numbers work, see:
* http://italian.about.com/library/weekly/aa042600a.htm
* Schaum's Outline of Italian Grammar By Joseph E. Germano, Conrad J. Schmitt.
* http://en.wiktionary.org/wiki/Appendix:Italian_numbers on large numbers also has full list 1..99.
* Proofreading and feedback from Erwin Feldhaus .
*
* Davide Vandelli davide.vandelli@gmail.com not only provided a dozen tweakings, he sent the
* corrected Italian.java source code!
*
* Why is this code written in an unusual way? see inwords.use
*
* @author Roedy Green, Canadian Mind Products
* @version 1.2 2009-05-02 correct spelling: milliardo to miliardo, milliardi to miliardi
* @since 2009-01-21
*/
public final class Italian implements ToWords
{
/**
* true if want additional debug output
*/
private static final boolean DEBUGGING = false;
private static final int FIRST_COPYRIGHT_YEAR = 2009;
/**
* undisplayed copyright notice
*
* @noinspection UnusedDeclaration
*/
private static final String EMBEDDED_COPYRIGHT =
"Copyright: (c) 2009-2017 Roedy Green, Canadian Mind Products, http://mindprod.com";
/**
* used to make a number negative
*/
private static final String MINUS = "meno";
/**
* word for one
*/
private static final String ONE = "uno";
/**
* word for one when combining
*/
private static final String ONE_COMBINING = "un";
/**
* word for zero
*/
private static final String ZERO = "zero";
private static final String[] groupNamePlural = {
/*
* American: unit, hundred, thousand, million, billion, trillion,
* quintillion
*/
/* 1 */ "",
/* 100 */ "cento",
/* 1,000 */ "mila",
/* 1,000,000 */ " milioni ",
/* 1,000,000,000 */ " miliardi ",
/* 1,000,000,000,000 */ " trilioni ",
/* 1,000,000,000,000,000 */ " triliardi ",
};
private static final String[] groupNameSingular = {
/*
* We only need up to a quintillion, since a long is about 9 * 10 ^ 18
*/
/*
* American: unit, hundred, thousand, million, billion, trillion,
* quintillion
*/
/* 1 */ "",
/* 100 */ "cento",
/* 1,000 */ "mille",
/* 1,000,000 */ " milione ",
/* 1,000,000,000 */ " miliardo ",
/* 1,000,000,000,000 */ " trilione ",
/* 1,000,000,000,000,000 */ " triliardo ",
};
private static final String[] lowName = {
/* zero is shown as "" since it is never used in combined forms */
/* 0 .. 990 */
/* 0 */ "",
/* 1 */ "uno",
/* 2 */ "due",
/* 3 */ "tre",
/* 4 */ "quattro",
/* 5 */ "cinque",
/* 6 */ "sei",
/* 7 */ "sette",
/* 8 */ "otto",
/* 9 */ "nove",
/* 10 */ "dieci",
/* 11 */ "undici",
/* 12 */ "dodici",
/* 13 */ "tredici",
/* 14 */ "quattordici",
/* 15 */ "quindici",
/* 16 */ "sedici",
/* 17 */ "diciassette",
/* 18 */ "diciotto",
/* 19 */ "diciannove",
/* 20 */ "venti",
/* 21 */ "ventuno",
/* 22 */ "ventidue",
/* 23 */ "ventitre",
/* 24 */ "ventiquattro",
/* 25 */ "venticinque",
/* 26 */ "ventisei",
/* 27 */ "ventisette",
/* 28 */ "ventotto",
/* 29 */ "ventinove",
/* 30 */ "trenta",
/* 31 */ "trentuno",
/* 32 */ "trentuno",
/* 33 */ "trentatre",
/* 34 */ "trentaquattro",
/* 35 */ "trentacinque",
/* 36 */ "trentasei",
/* 37 */ "trentasette",
/* 38 */ "trentotto",
/* 39 */ "trentanove",
/* 40 */ "quaranta",
/* 41 */ "quarantuno",
/* 42 */ "quarantadue",
/* 43 */ "quarantatre",
/* 44 */ "quarantaquattro",
/* 45 */ "quarantacinque",
/* 46 */ "quarantasei",
/* 47 */ "quarantasette",
/* 48 */ "quarantotto",
/* 49 */ "quarantanove",
/* 50 */ "cinquanta",
/* 51 */ "cinquantuno",
/* 52 */ "cinquantadue",
/* 53 */ "cinquantatre",
/* 54 */ "cinquantaquattro",
/* 55 */ "cinquantacinque",
/* 56 */ "cinquantasei",
/* 57 */ "cinquantasette",
/* 58 */ "cinquantotto",
/* 59 */ "cinquantanove",
/* 60 */ "sessanta",
/* 61 */ "sessantuno",
/* 62 */ "sessantadue",
/* 63 */ "sessantatre",
/* 64 */ "sessantaquattro",
/* 65 */ "sessantacinque",
/* 66 */ "sessantasei",
/* 67 */ "sessantasette",
/* 68 */ "sessantotto",
/* 69 */ "sessantanove",
/* 70 */ "settanta",
/* 71 */ "settantuno",
/* 72 */ "settantadue",
/* 73 */ "settantatre",
/* 74 */ "settantaquattro",
/* 75 */ "settantacinque",
/* 76 */ "settantasei",
/* 77 */ "settantasette",
/* 78 */ "settantotto",
/* 79 */ "settantanove",
/* 80 */ "ottanta",
/* 81 */ "ottantuno",
/* 82 */ "ottantadue",
/* 83 */ "ottantatre",
/* 84 */ "ottantaquattro",
/* 85 */ "ottantacinque",
/* 86 */ "ottantasei",
/* 87 */ "ottantasette",
/* 88 */ "ottantotto",
/* 89 */ "ottantanove",
/* 90 */ "novanta",
/* 91 */ "novantuno",
/* 92 */ "novantadue",
/* 93 */ "novantatré",
/* 94 */ "novantaquattro",
/* 95 */ "novantacinque",
/* 96 */ "novantasei",
/* 97 */ "novantasette",
/* 98 */ "novantotto",
/* 99 */ "novantanove",
};
/*
* HowToProcess many of this group is needed to form one of the succeeding group.
*/
private static final int[] divisor = {
/* 100 cento, 1,000 mille, 1,000,000 milione, 1,000,000,000 miliardo 1,000,000,000,000 trilione */
100, 10, 1000, 1000, 1000, 1000, 1000000 };
/**
* get Spanish word for one
*
* @param group 0= units 1=thousands etc.
*
* @return Italian word for one, possibly empty.
*/
private static String wordForOne( int group )
{
switch ( group )
{
case 0: // uno
return ONE;
case 1: // _ cento
case 2: // _ mille
return "";
default: // un milione
return ONE_COMBINING;
}
}
/**
* convert long integer into Italian words. e.g. -12.345 -> meno dodicimilatrecentoquarantacinque Handles
* negative and positive integers. on range -Long.MAX_VALUE .. Long.MAX_VALUE; It cannot handle Long.MIN_VALUE;
*
* @param num number to convert to words
*
* @return words
*/
@SuppressWarnings( { "WeakerAccess" } )
public static String inWords( long num )
{
if ( num == 0 )
{
return ZERO;
}
boolean negative = ( num < 0 );
if ( negative )
{
num = -num;
}
// s is where we accumulate the Italian, adding word on the left
// as we work toward higher order digits.
// We don't use a StringBuilder since they are designed to tack on the right
String s = "";
// Work least significant digit to most, right to left.
// until high order part is all 0s.
// group indexes group, not power of ten.
for ( int group = 0; num > 0; group++ )
{
// remdr is 0 to 3 digits to process, working from night
assert 0 <= group && group < divisor.length : group + " out of bounds";
int remdr = ( int ) ( num % divisor[ group ] );
// num now has digits to the left we will process later.
num = num / divisor[ group ];
if ( DEBUGGING )
{
out.println( "group:" + group + " remdr:" + remdr + " num:" + num + " s:" + s );
}
if ( remdr == 0 )
{
continue;
}
// the value of this group in words, without the units
String t;
if ( remdr == 1 )
{
t = wordForOne( group );
}
else if ( remdr < 100 )
{
t = lowName[ remdr ];
}
else
{
t = inWords( remdr );
}
s = t
+ ( remdr == 1 ? groupNameSingular[ group ] : groupNamePlural[ group ] )
+ s;
} // end for
s = s.trim();
if ( negative )
{
s = MINUS + " " + s;
}
return s;
} // end inWords
/**
* test harness
*
* @param args not used
*/
public static void main( String[] args )
{
Test.test( new Italian(), new DecimalDots() );
} // end main
/**
* @inheritDoc
*/
public String toWords( long num )
{
return Italian.inWords( num );
}
} // end Italian