<?xml version="1.0" encoding="UTF-8"?> <chapter annotations="slide" version="5.1" xml:id="sd1_workingWithNumbers_chap" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns="http://docbook.org/ns/transclusion" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:db="http://docbook.org/ns/docbook"> <title>Working with Numbers</title> <section xml:id="sd1_numbers_sect_boxAndUnbox"> <title>Boxing and Unboxing</title> <figure xml:id="sd1_numbers_fig_stack"> <title><classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/util/Stack.html">Stack</classname> of integer values</title> <informaltable border="0"> <colgroup width="83%"/> <colgroup width="17%"/> <tr> <td valign="top"><programlisting language="java">final Stack<Integer> values = new Stack<>(); values.push(3); values.push(1); values.push(10); while (!values.empty()) { final int i = values.pop(); System.out.println(i); }</programlisting></td> <td valign="top"><screen>10 1 3</screen></td> </tr> </informaltable> </figure> <figure xml:id="sd1_numbers_fig_collectionProperties"> <title><xref linkend="glo_Java"/> collection features</title> <itemizedlist> <listitem> <para>Supports searching of objects based on:</para> <itemizedlist> <listitem> <para><methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Object.html#equals-java.lang.Object-">public boolean equals</methodname>(<classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Object.html">Object</classname> obj)</para> </listitem> <listitem> <para><methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Object.html#hashCode--">public int hashCode()</methodname></para> </listitem> </itemizedlist> </listitem> <listitem> <para>Objects only, no primitive types!</para> </listitem> </itemizedlist> </figure> <figure xml:id="sd1_numbers_fig_stackBehindTheScenes"> <title>Behind the scenes</title> <informaltable border="0"> <colgroup width="48%"/> <colgroup width="50%"/> <tr> <td valign="top"><programlisting language="java">final Stack<Integer> values = new Stack<>(); values.push(3); values.push(1); values.push(10); while (!values.empty()) { System.out.println(values.pop(). getClass().getTypeName()); }</programlisting></td> <td valign="top"><screen>java.lang.Integer java.lang.Integer java.lang.Integer</screen></td> </tr> </informaltable> </figure> <figure xml:id="sd1_numbers_fig_boxingAndUnboxing"> <title><link xlink:href="https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html">Boxing and unboxing</link></title> <informaltable border="0"> <colgroup width="50%"/> <colgroup width="50%"/> <tr> <td valign="top"><programlisting language="none">int iPrimitive <co linkends="sd1_numbers_fig_boxingAndUnboxing-1" xml:id="sd1_numbers_fig_boxingAndUnboxing-1-co"/> = 7; Integer iInteger = <co linkends="sd1_numbers_fig_boxingAndUnboxing-2" xml:id="sd1_numbers_fig_boxingAndUnboxing-2-co"/> iPrimitive; int iPrimitiveFromInteger = <co linkends="sd1_numbers_fig_boxingAndUnboxing-3" xml:id="sd1_numbers_fig_boxingAndUnboxing-3-co"/> iInteger;</programlisting></td> <td valign="top"><programlisting language="none">int iPrimitive <co linkends="sd1_numbers_fig_conventional-1" xml:id="sd1_numbers_fig_conventional-1-co"/> = 7; Integer iInteger = <co linkends="sd1_numbers_fig_conventional-2" xml:id="sd1_numbers_fig_conventional-2-co"/> Integer.valueOf(iPrimitive); int iPrimitiveFromInteger = <co linkends="sd1_numbers_fig_conventional-3" xml:id="sd1_numbers_fig_conventional-3-co"/> iInteger.intValue();</programlisting></td> </tr> </informaltable> </figure> <informaltable border="1"> <colgroup width="50%"/> <colgroup width="50%"/> <tr> <th>Boxing and unboxing</th> <th><quote>Conventional</quote> <xref linkend="glo_Java"/></th> </tr> <tr> <td valign="top"><calloutlist> <callout arearefs="sd1_numbers_fig_boxingAndUnboxing-1-co" xml:id="sd1_numbers_fig_boxingAndUnboxing-1"> <para>Defining a primitive <code language="java">int</code> value.</para> </callout> <callout arearefs="sd1_numbers_fig_boxingAndUnboxing-2-co" xml:id="sd1_numbers_fig_boxingAndUnboxing-2"> <para>Creating an instance of <classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Integer.html">Integer</classname> by means of boxing.</para> </callout> <callout arearefs="sd1_numbers_fig_boxingAndUnboxing-3-co" xml:id="sd1_numbers_fig_boxingAndUnboxing-3"> <para>Assigning an <classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Integer.html">Integer</classname>'s value to a primitive <code language="java">int</code> by means of unboxing.</para> </callout> </calloutlist></td> <td valign="top"><calloutlist> <callout arearefs="sd1_numbers_fig_conventional-1-co" xml:id="sd1_numbers_fig_conventional-1"> <para>Defining a primitive <code language="java">int</code> value.</para> </callout> <callout arearefs="sd1_numbers_fig_conventional-2-co" xml:id="sd1_numbers_fig_conventional-2"> <para>Creating a new instance of <classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Integer.html">Integer</classname> using the class method <methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Integer.html#valueOf-int-">Integer valueOf(int i)</methodname>.</para> </callout> <callout arearefs="sd1_numbers_fig_conventional-3-co" xml:id="sd1_numbers_fig_conventional-3"> <para>Assigning an <classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Integer.html">Integer</classname>'s value to a primitive <code language="java">int</code> using the <methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Integer.html#intValue--">int intValue()</methodname> instance method.</para> </callout> </calloutlist></td> </tr> </informaltable> <figure xml:id="sd1_numbers_fig_stackBoxUnboxVsConventional"> <title><classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/util/Stack.html">Stack</classname> usage comparison</title> <informaltable border="0"> <colgroup width="50%"/> <colgroup width="50%"/> <tr> <td valign="top"><programlisting language="java">final Stack<Integer> values = new Stack<>(); values.push(Integer.valueOf(3)); values.push(Integer.valueOf(1)); values.push(Integer.valueOf(10)); while (!values.empty()) { System.out.println(values.pop().intValue()); }</programlisting></td> <td valign="top"><programlisting language="java">final Stack<Integer> values = new Stack<>(); values.push(3); values.push(1); values.push(10); while (!values.empty()) { System.out.println(values.pop()); }</programlisting></td> </tr> </informaltable> </figure> </section> <section xml:id="sd1_numbers_sect_numberParsing"> <title>Number Parsing</title> <figure xml:id="sd1_numbers_fig_parseIntegerString"> <title> Parsing <classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Integer.html">Integer</classname> user input</title> <informaltable border="0"> <colgroup width="65%"/> <colgroup width="35%"/> <tr> <td valign="top"><programlisting language="java">String userInput = "dummyValue"; try (final Scanner scanner = new Scanner(System.in)){ System.out.print("Enter an integer:"); userInput = scanner.nextLine(); final int value = Integer.parseInt(userInput); System.out.println("You entered " + value); } catch (final NumberFormatException e) { System.out.println("Sorry, but '" + userInput + "' is not an integer."); }</programlisting></td> <td valign="top"><screen>Enter an integer:-34 You entered -34</screen><screen>Enter an integer:five Sorry, but 'five' is not an integer.</screen></td> </tr> </informaltable> </figure> <qandaset defaultlabel="qanda" xml:id="sd1_numbers_qanda_whyDummyString"> <title>Why using <code language="java">String userInput = "dummyValue"</code>?</title> <qandadiv> <qandaentry> <question> <para>The former listing initializes the <code language="java">userInput</code> variable using a default value <code language="java">"dummyValue"</code>. Why is that?</para> <orderedlist> <listitem> <para>The variable <code language="java">userInput</code> is being assigned inside the <code language="java">try {...}</code> block before being used in any assignment.</para> </listitem> <listitem> <para>The <methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/util/Scanner.html#nextLine--">Scanner.nextLine()</methodname> method does not throw a <classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/NumberFormatException.html">NumberFormatException</classname>. Thus the only way to enter the <code language="java">catch {...}</code> clause is by executing of <code language="java">Integer.parseInt(userInput)</code> yielding a <classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/NumberFormatException.html">NumberFormatException</classname> . But this execution happens <emphasis>after</emphasis> assigning <code language="java">userInput = scanner.nextLine()</code>.</para> </listitem> </orderedlist> <para>So the dummy assignment <code language="java">String userInput = "dummyValue"</code> seems to be redundant. Is that true?</para> </question> <answer> <para>Actually the <xref linkend="glo_Java"/> compiler is not clever enough analyzing the <code language="java">try {...}</code> block. It cannot detect the impossibility of an uninitialized <code language="java">userInput</code> variable inside the <code language="java">catch {...}</code> clause.</para> <para>Since the possibility of am uninitialized <code language="java">userInput</code> variable using just <code language="java">String userInput;</code> causes a compile time error <code>Variable 'userInput' might not have been initialized</code>.</para> <para>Thus <code language="java">String userInput = null</code> would be appropriate as well since the value will actually never be used.</para> </answer> </qandaentry> </qandadiv> </qandaset> <figure xml:id="sd1_numbers_fig_parseIntegerToRadix"> <title>Parsing binary representation</title> <informaltable border="0"> <colgroup width="50%"/> <colgroup width="50%"/> <tr> <td valign="top"><programlisting language="java">final int value = Integer.parseInt("1101", 2); System.out.println("Value: " + value);</programlisting><screen>Value: 13</screen></td> <td valign="top"><programlisting language="java">final int value = Integer.parseInt("201", 2); System.out.println("Value: " + value)</programlisting><screen>Exception in thread "main" java.lang.NumberFormatException: For input string: "201" ... at de.hdm_stuttgart.sd1...</screen></td> </tr> </informaltable> </figure> <figure xml:id="sd1_numbers_fig_parseMethods"> <title>Standard parse methods</title> <informaltable border="0"> <colgroup width="50%"/> <colgroup width="50%"/> <tr> <td valign="top"><itemizedlist> <listitem> <para><methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Byte.html#parseByte-java.lang.String-">parseByte()</methodname></para> </listitem> <listitem> <para><methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Short.html#parseShort-java.lang.String-">parseShort()</methodname></para> </listitem> <listitem> <para><methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Integer.html#parseInt-java.lang.String-">parseInt()</methodname></para> </listitem> <listitem> <para><methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Long.html#parseLong-java.lang.String-">parseLong()</methodname></para> </listitem> </itemizedlist></td> <td valign="top"><itemizedlist> <listitem> <para><methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Float.html#parseFloat-java.lang.String-">parseFloat()</methodname></para> </listitem> <listitem> <para><methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Double.html#parseDouble-java.lang.String-">parseDouble()</methodname></para> </listitem> <listitem> <para><methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Boolean.html#parseBoolean-java.lang.String-">parseBoolean()</methodname></para> </listitem> </itemizedlist></td> </tr> </informaltable> </figure> <qandaset defaultlabel="qanda" xml:id="sd1_numbers_qanda_parseShortResult"> <title>Parsing <code language="java">short</code> values</title> <qandadiv> <qandaentry> <question> <para>Which outcome do you expect? Try to answer without prior execution.</para> <programlisting language="java">System.out.println(Short.parseShort("32767")); System.out.println(Short.parseShort("32768"));</programlisting> <para>Explain the result.</para> </question> <answer> <para><code language="java" xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Short.html#MAX_VALUE">MAX_VALUE</code> for primitive type <code language="java" xlink:href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.2.1-100-B">short</code> is <inlineequation> <m:math display="inline"> <m:mrow> <m:msup> <m:mi>2</m:mi> <m:mrow> <m:mi>16</m:mi> <m:mo>-</m:mo> <m:mi>1</m:mi> </m:mrow> </m:msup> <m:mo>-</m:mo> <m:mi>1</m:mi> </m:mrow> </m:math> </inlineequation> which equals 32767. Thus 32786 is no longer assignment compatible. So the first line will execute well but the second one yields a <classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/NumberFormatException.html">NumberFormatException</classname> at runtime :</para> <screen>Value:32767 Exception in thread "main" java.lang.NumberFormatException: Value out of range. Value:"32768" Radix:10 at java.lang.Short.parseShort(Short.java:120) at java.lang.Short.parseShort(Short.java:144) at de.hdm_stuttgart.sd1.ParseShortTooBig.main(ParseShortTooBig.java:8)</screen> </answer> </qandaentry> </qandadiv> </qandaset> <qandaset defaultlabel="qanda" xml:id="sd1_numbers_qanda_parseHexadecimal"> <title>Parsing <code language="java">short</code> values in hexadecimal representation</title> <qandadiv> <qandaentry> <question> <para>An image processing application yields the following type of data:</para> <programlisting language="java">String[] values = {"C9", "AF3", "B"}; // Hexadecimal string values</programlisting> <para>We are looking for a class method parsing these hex values and converting them to <code language="java">short</code>:</para> <programlisting language="java">/** * Convert a numerical value given as hexadecimal string to * its counterpart of type short. Example: * * "2B" equals 2 * 16 + 11 == 43 * * @param input String containing hexadecimal value. * @return the parsed short value. */ public static short getHexadecimal(final String input) { ... return ...; }</programlisting> <para>The provided sample data may then be processed like:</para> <programlisting language="java">final String[] values = {"C9", "AF3", "B"}; for (final String value: values) { System.out.println(value + ": " + getHexadecimal(value)); }</programlisting> <para>Result:</para> <screen>C9: 201 AF3: 2803 B: 11</screen> <tip> <para>Have a look to the binary parse example and think about representations.</para> </tip> </question> <answer> <para>Hexadecimal representation uses a radix value of 16 to be passed to <methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Short.html#parseShort-java.lang.String-int-">short parseShort(String s, int radix)</methodname>:</para> <programlisting language="java">/** * Convert a numerical value given as hexadecimal string to * its counterpart of type short. Example: * * "2B" equals 2 * 16 + 11 == 43 * * @param input String containing hexadecimal value. * @return the parsed short value. */ public static short getHexadecimal(final String input) { return Short.parseShort(input, 16); }</programlisting> </answer> <answer> <para><code language="java" xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/Short.html#MAX_VALUE">MAX_VALUE</code> for primitive type <code language="java" xlink:href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.2.1-100-B">short</code> is <inlineequation> <m:math display="inline"> <m:mrow> <m:msup> <m:mi>2</m:mi> <m:mrow> <m:mi>16</m:mi> <m:mo>-</m:mo> <m:mi>1</m:mi> </m:mrow> </m:msup> <m:mo>-</m:mo> <m:mi>1</m:mi> </m:mrow> </m:math> </inlineequation> which equals 32767. Thus 32786 is no longer assignment compatible. So the first line will execute well but the second one yields a <classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/lang/NumberFormatException.html">NumberFormatException</classname> at runtime :</para> <screen>Value:32767 Exception in thread "main" java.lang.NumberFormatException: Value out of range. Value:"32768" Radix:10 at java.lang.Short.parseShort(Short.java:120) at java.lang.Short.parseShort(Short.java:144) at de.hdm_stuttgart.sd1.ParseShortTooBig.main(ParseShortTooBig.java:8)</screen> </answer> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="sd1_numbers_sect_NumberFormatting"> <title>Number Formatting</title> <para/> <qandaset defaultlabel="qanda" xml:id="sd1_numbers_qanda_formatIntDoubleDate"> <title>Formatting <code language="java">int</code>, <code language="java">double</code> and <classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/time/LocalDate.html">LocaleDate</classname></title> <qandadiv> <qandaentry> <question> <para>Implement the following three overloaded class methods:</para> <programlisting language="java">/** * Print an int value using the given locale. Example: * * Using Locale.GERMANY a value of 1234567 should appear as "1.234.567" * * @param value The value to be formatted. * @param locale The locale to be used. */ static public void print(final int value, final Locale locale) {...}</programlisting> <programlisting language="java">/** * Print a double value using the given locale. Example: * * Using Locale.GERMANY a value of -123.456789 should appear as "-123,457" * * @param value The value to be formatted. * @param locale The locale to be used. */ static public void print(final double value, final Locale locale) {...}</programlisting> <programlisting language="java">/** * Print a {@link LocalDate} value using the given locale. Example: * * Using Locale.GERMANY the 22-nd of december 2024 should appear as "22. Dezember 2024". * * @param value The value to be formatted. * @param locale The locale to be used. */ static public void print(final LocalDate date, final Locale locale) {...}</programlisting> <para>You may use them as:</para> <programlisting language="java">for (final Locale locale : new Locale[]{Locale.GERMANY, Locale.JAPAN, Locale.US}) { System.out.println("Locale " + locale.getDisplayCountry()); print(1234567, locale); print(-123.456789, locale); print(LocalDate.of(2024, Month.DECEMBER, 22), locale); System.out.println("----------------------\n"); }</programlisting> <para>The expected output reads:</para> <screen>Locale Germany 1.234.567 -123,457 22. Dezember 2024 ---------------------- Locale Japan 1,234,567 -123.457 2024/12/22 ---------------------- Locale United States 1,234,567 -123.457 December 22, 2024 ----------------------</screen> <tip> <itemizedlist> <listitem> <para>Read the <classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/text/NumberFormat.html">NumberFormat</classname> documentation and its <methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/text/NumberFormat.html#getInstance-java.util.Locale-">static NumberFormat getInstance(Locale inLocale)</methodname> in particular. Also note its multiply overloaded <methodname>String format(...)</methodname> methods partly suiting your data type requirements.</para> </listitem> <listitem> <para>Regarding dates you may want to consider <classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/time/format/DateTimeFormatter.html">DateTimeFormatter</classname> providing the <methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/time/format/DateTimeFormatter.html#ofLocalizedDate-java.time.format.FormatStyle-">static DateTimeFormatter ofLocalizedDate(FormatStyle dateStyle)</methodname> method. Then read about class <classname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/time/format/FormatStyle.html">FormatStyle</classname> and the <methodname xlink:href="https://docs.oracle.com/javase/9/docs/api/java/time/format/DateTimeFormatter.html#withLocale-java.util.Locale-">DateTimeFormatter withLocale(Locale locale)</methodname> method.</para> </listitem> </itemizedlist> </tip> </question> <answer> <para>Implementing the first two methods is relatively simple:</para> <programlisting language="java">/** * Print an int value using the given locale. Example: * * Using Locale.GERMANY a value of 1234567 should appear as "1.234.567" * * @param value The value to be formatted. * @param locale The locale to be used. */ static public void print(final int value, final Locale locale) { final NumberFormat numberFormat = NumberFormat.getInstance(locale); System.out.println(numberFormat.format(value)); }</programlisting> <programlisting language="java">/** * Print a double value using the given locale. Example: * * Using Locale.GERMANY a value of -123.456789 should appear as "-123,457" * * @param value The value to be formatted. * @param locale The locale to be used. */ static public void print(final double value, final Locale locale) { final NumberFormat numberFormat = NumberFormat.getInstance(locale); System.out.println(numberFormat.format(value)); }</programlisting> <para>Processing dates is a bit cumbersome:</para> <programlisting language="java">/** * Print a {@link LocalDate} value using the given locale. Example: * * Using Locale.GERMANY the 22-nd of december 2024 should appear as "22. Dezember 2024". * * @param value The value to be formatted. * @param locale The locale to be used. */ static public void print(final LocalDate date, final Locale locale) { final DateTimeFormatter dateFormat = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG).withLocale(locale); System.out.println(dateFormat.format(date)); }</programlisting> </answer> </qandaentry> </qandadiv> </qandaset> </section> <section xml:id="sd1_numbers_sect_java.lang.Math"> <title>The java.lang.Math Class</title> <para/> </section> <section xml:id="sd1_numbers_sect_WorkingwithMoney"> <title>Working with Money</title> <para/> </section> <section xml:id="sd1_numbers_sect_GeneratingRandomNumbers"> <title>Generating Random Numbers</title> <para/> </section> </chapter>