/* * [German.java] * * Summary: Display a number in German 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-18 I suspect numbers over a million might be wrong. * 1.1 1999-01-19 Millionen on up pluralised, capitalised and a separate word. * 1.2 1999-01-21 make all language specific String literals into constants. */ package com.mindprod.inwords; /** * Display a number in German words. *

* e.g. -12345 displays as minus minus zwölftausenddreihundertfünfundvierzig. * * @author Roedy Green, Canadian Mind Products * @version 1.2 1999-01-21 make all language specific String literals into constants. * I studied German for one year in grade 13, so my knowledge of German counting * is pretty rusty. I found various examples of German counted * out words on the Internet and composed this algorithm * from the examples. * Special thanks go to Thomas Wagner <twagner@bix.com> * who explained my errors with Millions and up. * Why is this code written in an unusual way? see inwords.use * @since 1999-01-18 */ public final class German implements ToWords { private static final int FIRST_COPYRIGHT_YEAR = 1999; private static final String AND = "und"; /** * 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 ZERO = "null"; private static final String[] lowName = { /* zero is shown as "" since it is never used in combined forms */ /* 0 .. 19 */ "" /* 0 */, "ein" /* 1 combining form, eins, eine handled specially */, "zwei" /* 2 */, "drei" /* 3 */, "vier" /* 4 */, "f\u00fcnf" /* 5 f�nf f&uuum;nf */, "sechs" /* 6 */, "sieben" /* 7 */, "acht" /* 8 */, "neun" /* 9 */, "zehn" /* 10 */, "elf" /* 11 */, "zw\u00f6lf" /* 12 zwölf zwölf */, "dreizehn" /* 13 */, "vierzehn" /* 14 */, "f\u00fcnfzehn" /* 15 f�nfzehn fünfzehn */, "sechzehn" /* 16 */, "siebzehn" /* 17 */, "achtzehn" /* 18 */, "neunzehn" /* 19 */, "zwanzig" /* 20 */ }; private static final String[] ONE = { "eins", "ein", "eine" }; private static final String[] pluralGroupName = { /* We only need up to a trillion, since a long is about 9 * 10 ^ 18 */ /* * American: unit, hundred, thousand, million, billion, trillion, * quadrillion, quintillion */ "", "hundert", "tausend", "Millionen", "Milliarden", "Billionen", "Billiarden", "Trillionen", "Trilliarden" }; private static final String[] singularGroupName = { /* We only need up to a trillion, since a long is about 9 * 10 ^ 18 */ /* * American: unit, hundred, thousand, million, billion, trillion, * quadrillion, quintillion */ "", "hundert", "tausend", "Million", "Milliarde", "Billion", "Billiarde", "Trillion", "Trilliarde" }; private static final String[] tys = { /* 0, 10, 20, 30 ... 90 */ "", /* zero */ "zehn" /* 10 */, "zwanzig" /* 20 */, "drei\u00dfig" /* 30 drei�ig dreißig */, "vierzig" /* 40 */, "f\u00fcnfzig" /* 50 f�nfzig fünfzig */, "sechzig" /* 60 */, "siebzig" /* 70 */, "achtzig" /* 80 */, "neunzig" /* 90 */ }; 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 }; /** * test harness * * @param args not used */ public static void main( String[] args ) { Test.test( new German(), new DecimalDots() ); } // end main /** * convert long integer into German words. e.g. -12345 -> "minus zwölftausenddreihundertf�nfundvierzig". * 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 ) { 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 ]; String t; if ( remdr == 0 ) { continue; } else if ( remdr == 1 ) { if ( group == 0 ) { // eins on end of number, e.g. zweihunderteins t = ONE[ 0 ]; } else if ( group < 3 ) { // einhunert, einthousand t = ONE[ 1 ]; } else { // eine Million, eine Trillion t = ONE[ 2 ]; } } else if ( remdr < 20 ) { t = lowName[ remdr ]; } else if ( remdr < 100 ) { int units = remdr % 10; int tens = remdr / 10; t = tys[ tens ]; if ( units > 0 ) { /* like one and twenty, reversed einundzwanzig */ t = lowName[ units ] + AND + t; } } else { t = toWords( remdr ); } /* space before Million and up */ boolean leftPad = ( group > 2 ); /* space after Million and up */ boolean rightPad = ( group > 2 ); boolean plural = ( remdr > 1 ); s = t + ( leftPad ? " " : "" ) + ( plural ? pluralGroupName[ group ] : singularGroupName[ group ] ) + ( rightPad ? " " : "" ) + s; } // end for s = s.trim(); if ( negative ) { s = MINUS + " " + s; } return s; } // end inWords } // end German