/* * [Swedish.java] * * Summary: Display a number in Swedish 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 1999-01-14 same as the Norwegian version, just different tables. * 1.1 1999-01-21 make all language specific String literals into constants. * 1.2 1999-01-30 corrections: * 20 tjuge -> tjugo * 40 "f\u00f8rtio" f&oslashrtiof�rtio -> fyrtio * 60 sekstio -> sextio * remove "och" * use "ett" all the time for "one", never "en" * remove space before and after groupname. * suppress one before a group, except in the middle of a number. * e.g. tusenetthundra but just plain hundra. * 1.3 1999-01-31 more corrections from Danny Kohn * 21.199 tjugoetttusenetthundranittionio -> tjugoentusenetthundranittionio * 100.000 hundratusen -> etthundratusen * 1.000.000 miljon -> en miljon * 10.000.000 tiomiljoner -> tio miljoner * 10.000.001 tiomiljonerett (no space) * 1.000.000.000 miljard -> en miljard. * 1.000.000.001 miljardett -> enmiljardett (no space) * Introduced gender, coreInWords. * 1.4 1999-02-01 gender: natural and neuter (mostly words * ending * in "n" and "t") */ package com.mindprod.inwords; /* * 21.199 tjugoetttusenetthundranittionio -> tjugoentusenetthundranittionio * 100.000 hundratusen -> etthundratusen * 1.000.000 miljon -> en miljon * 10.000.000 tiomiljoner -> tio miljoner * 10.000.001 tiomiljonerett (no space) * 1.000.000.000 miljard -> en miljard. * 1.000.000.001 miljardett -> enmiljardett (no space) * Introduced gender, coreInWords. * 21.199 tjugoetttusenetthundranittionio -> tjugoentusenetthundranittionio * 100.000 hundratusen -> etthundratusen * 1.000.000 miljon -> en miljon * 10.000.000 tiomiljoner -> tio miljoner * 10.000.001 tiomiljonerett (no space) * 1.000.000.000 miljard -> en miljard. * 1.000.000.001 miljardett -> enmiljardett (no space) * Introduced gender, coreInWords. */ /** * Display a number in Swedish words. *

* e.g. -12.345 is dispulayd as minus minus tolvtusentrehundrafyrtiofem. * * @author Roedy Green, Canadian Mind Products * @version 1.3 1999-01-31 more corrections from Danny Kohn * Special thanks go to Tarjei �vergaard <tarjeio@microdesign.no> * who provided all the information about Norwegian and Swedish * counting used to write this program. Danny Kohn danny.kohn@systematik.se did most of the work. * @since 1999-01-14 */ public final class Swedish implements ToWords { private static final int FIRST_COPYRIGHT_YEAR = 1999; /* gender enumeration */ private static final int NATURAL = 0; private static final int NEUTER = 1; /** * 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 = "minus"; private static final String PLURAL = "er"; private static final String ZERO = "noll"; private static final String[] groupName = { /* We only need up to a trillion, since a long is about 9 * 10 ^ 18 */ /* * After that it goes trilliard, kvadrilion, kvadrilliard, kvintillion, * Kvintilliard */ /* * American unit, hundred, thousand, million, billion, trillion, * quadrillion, quintillion */ "", "hundra", "tusen", "miljon", "miljard", "biljon", "biljard", "triljon" }; private static final String[] naturalLowName = { /* zero is shown as "" since it is never used in combined forms */ /* 0 .. 19 */ "", "ett", "tv\u00e5" /* tv� två */, "tre", "fyra", "fem", "sex", "sju", "\u00e5tta" /* �tta åtte */, "nio", "tio", "elva", "tolv", "tretton", "fjorton", "femton", "sexton", "sjutton", "arton", "nitton" }; private static final String[] ONE = { "ett", "en" };/* natural, neuter */ private static final String[] tys = { /* 0, 10, 20, 30 ... 90 */ "", "", "tjugo", "trettio", "fyrtio", "femtio", "sextio", "sjuttio", "\u00e5ttio" /* �ttio åtti */, "nittio" }; private static final int[] divisor = { /* * how many of this group is needed to form one of the succeeding group. */ /* * American unit, hundred, thousand, million, billion, trillion, * quadrillion, quintillion */ 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 1:/* hundra */ /* "ett" */ return NATURAL; case 2:/* tusen */ case 3:/* miljon */ case 4:/* miljard */ case 5:/* biljon */ case 6:/* biljard */ case 7:/* triljon */ /* "en" */ return NEUTER; 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 digit 1 changes gender. All others are identical. if ( number == 1 ) { return ONE[ gender ]; } else { return naturalLowName[ number ]; } } // end lowName /** * convert long integer into Swedish words. e.g. -12.345 -> "minus tolvtusentrehundrafyrtiofem". 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 * @param unitsGroup groupName index for the units of this number e.g. 2 if this number is measured in thousands. * * @return words */ private static String toWordsCore( long num, int unitsGroup ) { 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 == 1 ) { // one is handled three possible ways: // "ett" (natural), "en" (neuter) and suppressed // 1 = ett // 100 = hundra // 101 = hundraett // 1.000 = tusen // 1.001 = tusenett // 21.199 = tjugoentusenetthundranittionio // 100.000 = etthundrahusen // 1.000.000 = en miljon // 1.000.001 = enmiljonett // 10.000.000 = tio miljoner // 10.000.001 = tiomiljonerett // 1.000.000.000 = en miljard // 1.000.000.001 = enmiljardett switch ( group ) { case 1: /* hundra */ case 2: /* tusen */ // Suppress "en"/"ett" before hundra and tusen, // except as multiplier e.g. 100.000 etthundratusen // or when there is more to left e.g. 21.199 // tjugoentusenetthundranittionio boolean suppress = ( num == 0 /* nothing on left */ && unitsGroup == 0/* not multiplier */ ); t = ( suppress ) ? "" : lowName( remdr, gender ); break; case 0: /* units */ case 3: /* miljon */ case 4: /* miljard */ case 5: /* biljon */ case 6: /* biljard */ case 7: /* triljon */ default: t = lowName( remdr, gender ); break; } // end switch } 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 ) { t += lowName( units, gender ); } } else { // recursive t = toWordsCore( remdr, group ); } boolean plural = ( remdr > 1 ) && ( group > 2 );// only above 1000 // considered plural boolean leftPad = ( s.length() == 0 && group >= 3 ); s = t + ( leftPad ? " " : "" ) + groupName[ group ] + ( plural ? PLURAL : "" ) + 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 Swedish(), new DecimalDots() ); } // end main /** * convert long integer into Swedish words. e.g. -12.345 -> "minus tolvtusentrehundrafyrtiofem". 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", "WeakerAccess", "WeakerAccess" } ) public String toWords( long num ) { return toWordsCore( num, 0 ); } // end toWords } // end Swedish