/* * [Icelandic.java] * * Summary: Display a number in Icelandic 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.1 1999-01-20 remove &aacute from middle a in 80 áttatíu * &aacutettat&iacuteu * Parallels way Swedish code works. * 1.2 1999-01-21 make all language specific String literals into * constants. * 1.3 1999-01-23 changed based on information from David Holm's * relatives and friends. * The "og" goes between the tys and the * units, * rather than after the hundreds. * The masculine form, rather than the neuter * form, * is used for genderless counting. * The singular form of thusund had the acute on * the wrong u. * Thusund should be neuter, rather than feminine. * The plural of thusund is thusund. * The plural of milljardur is milljardar. * The plural of billjardur is billjardar. * 1.4 1999-01-26 more changed based on input from David Holm's * relatives and friends. * add gender test for TYs. * add og in 101 * gender match on 101,000 etc. * 1.5 1999-01-31 change way inWordsCore works, now gets * unitsGroup rather than gender. * 1.6 1999-02-04 changes from David Holm's father * 90 nítíu -> níutíu * og before last group. * 21 == tuttugu og einn * 120 == eitt hundrað og tuttugu * 121 == eitt hundrað tuttugu og einn * 1.200 == eitt þ�sund og tvö hundruð * 21.200 == tuttugu og eitt þ�sund og tvö hundruð * 100.000.000 == eitt hundrað milljónir * 100.002.000 == eitt hundrað milljónir og tvö * þ�sund * 100.032.000 == eitt hundrað milljónir þrjátiu * og * tvö þ�sund * 100.200.000 == eitt hundrað milljónir og tvö * hundruð þ�sund * 100.220.000 == eitt hundrað milljónir tvö * hundruð og tuttugu þ�sund. * 1.7 1999-02-04 100.101.000 == eitt hundrað milljónir eitt * hundrað og eitt þ�sund * previously had two ogs. */ package com.mindprod.inwords; /** * Display a number in Icelandic words. *

* e.g. -12345 is displayed as mínus tólf þúsund og þrjú hundruð fjö * rutíu og fimm * * @author Roedy Green, Canadian Mind Products * @version 1.7 1999-02-04 100.101.000 == eitt hundrað milljónir eitt * hundrað og eitt þ�sund * previously had two ogs. * @since 1999 */ public final class Icelandic implements ToWords { private static final int FEMININE = 1; private static final int FIRST_COPYRIGHT_YEAR = 1999; /* gender enumeration */ private static final int MASCULINE = 0; private static final int NEUTER = 2; private static final String AND = "og"; /** * undisplayed copyright notice * * @noinspection UnusedDeclaration */ private static final String EMBEDDED_COPYRIGHT = "Copyright: (c) 1999-2017 Roedy Green, Canadian Mind Products, http://mindprod.com"; private static final String MINUS = "m\u00ednus"/* mínus mínus */; private static final String ZERO = "n\u00fall";/* n�ll núll */ private static final String[] feminineLowName = { /* numbers 0 to 4, used before milljon, billjon, trilljon */ "" /* 0 */, "ein" /* 1 ein */, "tv\u00e6r" /* 2 tv�r tvær */, "\u00ferj\u00e1r" /* 3 þrjár þrjár */, "fj\u00f3rar" /* 4 fjórar fjórar */ }; private static final String[] masculineLowName = { /* numbers 0 to 4, used before units, milliardur and billiardur */ "" /* 0 */, "einn" /* 1 einn */, "tveir" /* 2 tveir */, "\u00fer\u00edr" /* 3 þrír þrír */, "fj\u00f3rir" /* 4 fjórir fjóir */, "fimm" /* 5 fimm */, "sex" /* 6 sex */, "sj\u00f6" /* 7 sjö sjö */, "\u00e1tta" /* 8 átta átta */, "n\u00edu" /* 9 níu níu */, "t\u00edu" /* 10 tíu tíu */, "ellefu" /* 11 ellefu */, "t\u00f3lf" /* 12 tólf tólf */, "\u00ferett\u00e1n" /* 13 þrettán þrettán */, "fj\u00f3rt\u00e1n" /* 14 fjórtán fjórtán */, "fimmt\u00e1n" /* 15 fimmtán fimmtán */, "sext\u00e1n" /* 16 sextán sextán */, "sautj\u00e1n" /* 17 sautján sautján */, "\u00e1tj\u00e1n" /* 18 átján átján */, "n\u00edtj\u00e1n" /* 19 nítján nítján */ }; private static final String[] neuterLowName = { /* zero is shown as "" since it is never used in combined forms */ /* numbers 0 to 20, used before hundrad and thusund */ "" /* 0 */, "eitt" /* 1 */, "tv\u00f6" /* 2 tvö tvö */, "\u00ferj\u00fa" /* 3 þrj� þrjú */, "fj\u00f6gur" /* 4 fjögur fjögur */ }; private static final String[] pluralGroupName = { /* We only need up to a trillion, since a long is about 9 * 10 ^ 18 */ "" /* 1 */, "hundru\u00f0" /* 100 hundruð hundruð */, "\u00fe\u00fasund" /* 1,000 þ�sund þúsund */, "millj\u00f3nir" /* 1,000,000 milljónir milljónir */, "milljar\u00f0ar" /* 1,000,000,000 milljarðar milljarðar */, "billj\u00f3nir" /* 1,000,000,000,000 billjónir billjónir */, "billjar\u00f0ar" /* * 1,000,000,000,000,000 billjarðar billjarðar */, "trillj\u00f3nir" /* * 1,000,000,000,000,000,000 trilljónir * trilljónir */ }; private static final String[] singularGroupName = { /* We only need up to a trillion, since a long is about 9 * 10 ^ 18 */ "" /* 1 */, "hundra\u00f0" /* 100 hundrað hundrað */, "\u00fe\u00fasund" /* 1,000 þ�sund þúsund */, "millj\u00f3n" /* 1,000,000 milljón milljón */, "milljar\u00f0ur" /* 1,000,000,000 milljarður milljarður */, "billj\u00f3n" /* 1,000,000,000,000 billjón billjón */, "billjar\u00f0ur" /* * 1,000,000,000,000,000 billjarður billjarður */, "trillj\u00f3n" /* * 1,000,000,000,000,000,000 trilljón trilljón */ }; private static final String[] tys = { /* numbers 0, 10, 20, 30 ... 90 */ "" /* 0 */, "" /* 10 */, "tuttugu" /* 20 tuttugu */, "\u00ferj\u00e1t\u00edu" /* * 30 þrjátíu þrjátíu */, "fj\u00f6rut\u00edu" /* 40 fjörutíu fjörutíu */, "fimmt\u00edu" /* 50 fimmtíu fimmtíu */, "sext\u00edu" /* 60 sextíu sextíu */, "sj\u00f6t\u00edu" /* 70 sjötíu sjötíu */, "\u00e1tta\u00edu" /* 80 áttatíu áttatíu */, "n\u00edut\u00edu" /* 90 níutíu n&iuacute;tíu */ }; private static final int[] divisor = { /* * how many of this group is needed to form one of the succeeding group. */ 100, 10, 1000, 1000, 1000, 1000, 1000, 1000 }; /** * what is the gender of the given group word. * * @param group 0=units 1=hundreds 2=thousands etc. * * @return gender of that group word, coded numerically. */ private static int groupGender( int group ) { switch ( group ) { case 0:/* units */ case 4:/* milljarðar */ case 6:/* billjarðar */ return MASCULINE; case 1:/* hundreds */ case 2:/* thousands */ return NEUTER; case 3:/* milljón */ case 5:/* billjónir */ case 7:/* trilljónir */ return FEMININE; default: throw new IllegalArgumentException(); } // end switch } // end gender /** * get word for number, based on gender of succeeding groupname * * @param number 0..19 to put into words. * @param gender of succeeding group word, numerically coded. * * @return String in words, not including the group name. */ private static String lowName( int number, int gender ) { // only digits 1..4 change gender. All others remain masculine. if ( number <= 4 ) { switch ( gender ) { case MASCULINE: return masculineLowName[ number ]; case FEMININE: return feminineLowName[ number ]; case NEUTER: return neuterLowName[ number ]; default: throw new IllegalArgumentException(); } // end switch } else { return masculineLowName[ number ]; } } // end lowName /** * convert long integer into Icelandic words. e.g. -12345 -> "mínus tólf þ�sund og þrj� * hundruð fjörutíu og fimm". * Handles negative and positive integers on range -Long.MAX_VALUE .. Long.MAX_VALUE; * * @param num number to convert to words. * @param unitsGroup units of measure for num, e.g. 0=units 1=hundreds, 2=thousands etc. * @param suppressAnd true if "og" (and) has already appeared to the right in composing this number. This will * suppress any more "og"s. It cannot handle Long.MIN_VALUE; * * @return number in words. */ private static String toWordsCore( long num, int unitsGroup, boolean suppressAnd ) { if ( num == 0 ) { return ZERO; } boolean negative = ( num < 0 ); if ( negative ) { num = -num; } String s = ""; // Work least significant digit to most, right to left. // until high order part is all 0s. for ( int group = 0; num > 0; group++ ) { int remdr = ( int ) ( num % divisor[ group ] ); num = num / divisor[ group ]; // gender of succeeding group word int gender = ( group == 0 ? groupGender( unitsGroup ) : groupGender( group ) ); String t; if ( remdr == 0 ) { continue; } else if ( remdr < 20 ) { t = lowName( remdr, gender ); } else if ( remdr < 100 ) { int units = remdr % 10; int tens = remdr / 10; t = tys[ tens ]; if ( units != 0 ) { // This "og" goes in, whether or not there already is one to // the right, // even if we are generally suppressing them. t += " " + AND + " " + lowName( units, gender ); suppressAnd = true; } } else { t = toWordsCore( remdr, group, suppressAnd ); // avoid any more "og"s (ands). // Ideally toWordsCore would return both a String // and a suppressAnd flag. It is so clumsy in Java to do that, // that I have resorted to this kludge instead. if ( t.contains( AND + " " ) ) { suppressAnd = true; } } boolean and = !suppressAnd && ( num != 0 ) && ( remdr != 0 ); // avoid putting in more than one "og" per number, except in // numbers like 21.200 == tuttugu og eitt þ�sund og tvö hundruð if ( and ) { suppressAnd = true; } boolean plural = ( remdr > 1 ); s = ( and ? AND + " " : "" ) + t + " " + ( plural ? pluralGroupName[ group ] : singularGroupName[ 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 Icelandic(), new DecimalDots() ); } // end main /** * convert long integer into Icelandic words. e.g. -12345 -> "mínus tólf þ�sund og þrj� * hundruð fjörutíu og fimm". * 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 String toWords( long num ) { return toWordsCore( num, 0, false ); } // end inWords } // end Icelandic