Skip to content
Snippets Groups Projects
workingWithNumbers.xml 41.7 KiB
Newer Older
Goik Martin's avatar
Goik Martin committed
<?xml version="1.0" encoding="UTF-8"?>
<chapter annotations="slide" version="5.1"
         xml:id="sd1_workingWithNumbers_chap"
Goik Martin's avatar
Goik Martin committed
         xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
Goik Martin's avatar
Goik Martin committed
         xmlns:xi="http://www.w3.org/2001/XInclude"
         xmlns:svg="http://www.w3.org/2000/svg"
         xmlns:ns="http://docbook.org/ns/transclusion"
Goik Martin's avatar
Goik Martin committed
         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>
Goik Martin's avatar
Goik Martin committed

  <section xml:id="sd1_numbers_sect_boxAndUnbox">
    <title>Boxing and Unboxing</title>

    <figure xml:id="sd1_numbers_fig_stack">
      <title><classname
Goik Martin's avatar
Goik Martin committed
      xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Stack.html">Stack</classname>
      of integer values</title>

      <informaltable border="0">
        <colgroup width="87%"/>
        <colgroup width="13%"/>
Goik Martin's avatar
Goik Martin committed
          <td valign="top"><programlisting language="java">final Stack&lt;Integer&gt; values = new Stack&lt;&gt;();

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
Goik Martin's avatar
Goik Martin committed
              xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#equals(java.lang.Object)">public
              boolean equals</methodname>(<classname
Goik Martin's avatar
Goik Martin committed
              xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html">Object</classname>
              obj)</para>
            </listitem>

            <listitem>
              <para><methodname
Goik Martin's avatar
Goik Martin committed
              xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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&lt;Integer&gt; values =
  new Stack&lt;&gt;();

values.push(3);
values.push(1);
values.push(10);

while (!values.empty()) {
Goik Martin's avatar
Goik Martin committed
  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"
Goik Martin's avatar
Goik Martin committed
                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"
Goik Martin's avatar
Goik Martin committed
                xml:id="sd1_numbers_fig_conventional-3-co"/>
  iInteger.intValue();</programlisting></td>
        </tr>
      </informaltable>

      <informaltable border="1" role="slideExclude">
        <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
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html">Integer</classname>
                using the class method <methodname
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html">Integer</classname>'s
                value to a primitive <code language="java">int</code> using
                the <methodname
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html#intValue()">int
                intValue()</methodname> instance method.</para>
              </callout>
            </calloutlist></td>
        </tr>
      </informaltable>

    <figure xml:id="sd1_numbers_fig_stackBoxUnboxVsConventional">
      <title>Boxing syntax comparison</title>

      <informaltable border="0">
        <colgroup width="50%"/>

        <colgroup width="50%"/>

        <tr>
Goik Martin's avatar
Goik Martin committed
          <td valign="top"><programlisting language="java">final Stack&lt;Integer&gt; values
 = new Stack&lt;&gt;();

values.push(Integer.valueOf(3));
values.push(Integer.valueOf(1));
values.push(Integer.valueOf(10));

while (!values.empty()) {
Goik Martin's avatar
Goik Martin committed
  System.out.println(values.pop().
     intValue());
}</programlisting></td>

          <td valign="top"><programlisting language="java">final Stack&lt;Integer&gt; values =
  new Stack&lt;&gt;();

values.push(3);
values.push(1);
values.push(10);

while (!values.empty()) {
Goik Martin's avatar
Goik Martin committed
  System.out.println(values.pop());
}</programlisting></td>
        </tr>
      </informaltable>
    </figure>

    <qandaset defaultlabel="qanda"
              xml:id="sd1_numbers_qanda_boxing_int2Double">
      <title>Auto boxing int to Double?</title>

      <qandadiv>
        <qandaentry>
          <question>
            <para>Consider the following two code snippets:</para>
            <informaltable border="0">
              <tr>
                <td valign="top"><programlisting language="java">Double d = 3.0;</programlisting></td>
                <td valign="top"><programlisting language="java">Double d = 3;</programlisting></td>
              </tr>
              <tr>
                <td valign="top">o.K.</td>

                <td valign="top"><para>Compile time error:</para><screen>Incompatible types.
Required: java.lang.Double
Found: int</screen></td>
              </tr>
            </informaltable>

            <para>Explain this result. Hint: You may want to read <link
            xlink:href="https://docs.oracle.com/javase/specs/jls/se12/html/jls-5.html">chapter
            5</link> and <link
            xlink:href="https://docs.oracle.com/javase/specs/jls/se12/html/jls-5.html#jls-5.2">section
            5.2</link> in particular from the <link
            xlink:href="https://docs.oracle.com/javase/specs/jls/se12/html/">The
            Java® Language Specification</link>.</para>
          </question>

          <answer>
            <para><quote>3.0</quote> is a double literal. For the sake of
            clarification we may rewrite the working code snippet:</para>

            <programlisting language="java">double doubleValue = 3.0;
Double d = doubleValue;</programlisting>

            <para>With autoboxing on offer the compiler will silently box the
            value of type <code language="java">double</code> into a
            corresponding instance of type
            <classname>Double</classname>.</para>

            <para>On contrary <quote>3</quote> is an <code
            language="java">int</code> literal allowing for re-writing the
            second snippet as:</para>

            <programlisting language="java">int intValue = 3.0;
Double d = intValue;</programlisting>

            <para>The <quote
            xlink:href="https://docs.oracle.com/javase/specs/jls/se12/html/jls-5.html#jls-5.1.7">Boxing
            Conversion</quote> section does not define an <code
            language="java">int</code> to <classname>Double</classname> boxing
            conversion: The compiler will thus not perform auto boxing from
            <code>int</code> do <classname>Double</classname>.</para>

            <para>An <code language="java">int</code> could however be
            auto-boxed into an <classname>Integer</classname>. But
            <classname>Double</classname> not being a subtype of
            <classname>Integer</classname> disallows a widening reference
            conversion.</para>
          </answer>
        </qandaentry>
      </qandadiv>
    </qandaset>
  </section>

  <section xml:id="sd1_numbers_sect_numberParsing">
    <title>Number Parsing</title>

    <figure xml:id="sd1_numbers_fig_parseIntegerString">
      <title>Parsing <classname
Goik Martin's avatar
Goik Martin committed
      xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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 = null;
try (final Scanner scanner =
Goik Martin's avatar
Goik Martin committed
  new Scanner(System.in)){
  System.out.print("Enter an integer:");
  userInput = scanner.nextLine();
Goik Martin's avatar
Goik Martin committed
  final int value = Integer.parseInt(userInput);
  System.out.println("You entered " + value);
} catch (final NumberFormatException e) {
  System.out.println("Error: No integer value");
}</programlisting></td>

          <td valign="top"><screen>Enter an integer:-34
Goik Martin's avatar
Goik Martin committed
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 =

      <qandadiv>
        <qandaentry>
          <question>
            <para>The former listing initializes the <code
            language="java">userInput</code> variable using a default value
            <code language="java">null</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
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Scanner.html#nextLine()">Scanner.nextLine()</methodname>
                method does not throw a <classname
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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 = null</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. The catch clause can only be reached by inadequate user
            input causing the <methodname>parseInt(...)</methodname> method.
            In particular the <methodname>nextLine(...)</methodname> being
            unable to throw a <classname
            xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/NumberFormatException.html">NumberFormatException</classname>
            cannot be the culprit for entering the <code
            language="java">catch</code> clause. Thus if a <classname
            xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/NumberFormatException.html">NumberFormatException</classname>
            is being thrown our <code language="java">userInput</code>
            variable will already carry a user entered input string. The
            compiler however cannot analyze this type of dependency.</para>
            <para>Thus the possibility of an uninitialized <code
            language="java">userInput</code> variable using just <code
            language="java">String userInput;</code> would cause a compile
            time error <code>Variable 'userInput' might not have been
            initialized</code>.</para>

            <para><code language="java">So userInput = null</code> is
            sufficient for keeping the compiler happy and inside the catch
            clause the variable will definitively carry a<classname>
            String</classname> reference.</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>
Goik Martin's avatar
Goik Martin committed
          <td valign="top"><programlisting language="java">final int value =
   Integer.parseInt("1101", 2);
Goik Martin's avatar
Goik Martin committed
System.out.println("Value: " + value);</programlisting><screen>Value: 13</screen></td>
          <td valign="top"><programlisting language="java">final int value =
  Integer.parseInt("201", 2);
Goik Martin's avatar
Goik Martin committed
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
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Byte.html#parseByte(java.lang.String)">parseByte()</methodname></para>
              </listitem>

              <listitem>
                <para><methodname
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Short.html#parseShort(java.lang.String)">parseShort()</methodname></para>
              </listitem>

              <listitem>
                <para><methodname
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html#parseInt(java.lang.String)">parseInt()</methodname></para>
              </listitem>

              <listitem>
                <para><methodname
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Long.html#parseLong(java.lang.String)">parseLong()</methodname></para>
              </listitem>
            </itemizedlist></td>

          <td valign="top"><itemizedlist>
              <listitem>
                <para><methodname
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Float.html#parseFloat(java.lang.String)">parseFloat()</methodname></para>
              </listitem>

              <listitem>
                <para><methodname
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Double.html#parseDouble(java.lang.String)">parseDouble()</methodname></para>
              </listitem>

              <listitem>
                <para><methodname
Goik Martin's avatar
Goik Martin committed
                xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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"
Goik Martin's avatar
Goik Martin committed
            xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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
Goik Martin's avatar
Goik Martin committed
            xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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
Goik Martin's avatar
Goik Martin committed
            xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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"
Goik Martin's avatar
Goik Martin committed
            xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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
Goik Martin's avatar
Goik Martin committed
            xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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>

    <figure xml:id="sd1_numbers_fig_locale">
      <title>Excerpt from <classname
Goik Martin's avatar
Goik Martin committed
      xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Locale.html">java.util.Locale</classname></title>

      <para>A Locale object represents a specific geographical, political, or
      cultural region.</para>

      <para>An operation that requires a Locale to perform its task is called
      locale-sensitive and uses the Locale to tailor information for the
      user.</para>

      <para>For example, displaying a number is a locale-sensitive operation:
      Numbers should be formatted according to the customs and conventions of
      the user's native country, region, or culture.</para>
    </figure>

    <figure xml:id="sd1_numbers_fig_localeProperties">
      <title><classname
Goik Martin's avatar
Goik Martin committed
      xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Locale.html">Locale</classname>
      properties</title>

      <itemizedlist>
        <listitem>
          <para>Language</para>
        </listitem>

        <listitem>
          <para>Encoding</para>
        </listitem>

        <listitem>
          <para>Country</para>
        </listitem>

        <listitem>
          <para>Extensible</para>
        </listitem>
      </itemizedlist>
    </figure>

    <figure xml:id="sd1_numbers_fig_constructNumberFormat">
      <title>Get a <classname
Goik Martin's avatar
Goik Martin committed
      xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/text/NumberFormat.html">NumberFormat</classname>
      instance</title>

      <informaltable border="0">
        <tr>
          <td valign="top"><programlisting language="none">final NumberFormat standard = new DecimalFormat();
System.out.println(standard.format(<emphasis role="red">1234.5678</emphasis>));
final NumberFormat de =
    DecimalFormat.getInstance(Locale.GERMANY);
System.out.println(de.format(<emphasis role="red">1234.5678</emphasis>));</programlisting></td>
          <td valign="top"><screen><emphasis role="red">1234.5678</emphasis>
<emphasis role="red">1.234,568</emphasis></screen></td>
        </tr>
      </informaltable>
    </figure>

    <figure xml:id="sd1_numbers_fig_customFormat">
      <title>Create a custom formatter</title>

Goik Martin's avatar
Goik Martin committed
      <programlisting language="java">final DecimalFormatSymbols unusualSymbols =
  new DecimalFormatSymbols(Locale.getDefault());
unusualSymbols.setDecimalSeparator(<emphasis role="red">'|'</emphasis>);
unusualSymbols.setGroupingSeparator(<emphasis role="red">'^'</emphasis>);

final String strange = "#,##0.###";
final DecimalFormat weirdFormatter = new DecimalFormat(strange, unusualSymbols);
weirdFormatter.setGroupingSize(4);

System.out.println(weirdFormatter.format(12345.678));</programlisting>

      <screen>1<emphasis role="red">^</emphasis>2345<emphasis role="red">|</emphasis>678</screen>
    </figure>

    <qandaset defaultlabel="qanda"
              xml:id="sd1_numbers_qanda_getAvailableLocales">
      <title><classname
Goik Martin's avatar
Goik Martin committed
      xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Locale.html">Locale</classname>
      definitions</title>

      <qandadiv>
        <qandaentry>
          <question>
            <para>Each <xref linkend="glo_JRE"/> ships with a set of available
            <classname
Goik Martin's avatar
Goik Martin committed
            xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Locale.html">Locale</classname>
            definitions. Write a simple program to get the following
            list:</para>

            <screen>160 locales available:
Locale: Arabic(ar_AE)
Locale: Arabic(ar_JO)
Locale: Arabic(ar_SY)
Locale: Croatian(hr_HR)
...
Locale: Indonesian(in_ID)
Locale: English(en_GB)</screen>

            <tip>
              <para>Read the documentation of <classname
Goik Martin's avatar
Goik Martin committed
              xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Locale.html">Locale</classname>
              to find appropriate methods.</para>
            </tip>
          </question>

          <answer>
            <programlisting language="java">System.out.println(Locale.getAvailableLocales().length + " locales available:");
for (final Locale l: Locale.getAvailableLocales()) {
  System.out.println("Locale: " + l.getDisplayLanguage() + "(" + l + ")");
}</programlisting>
          </answer>
        </qandaentry>
      </qandadiv>
    </qandaset>

    <qandaset defaultlabel="qanda"
              xml:id="sd1_numbers_qanda_formatIntDoubleDate">
      <title>Formatting <code language="java">int</code>, <code
      language="java">double</code> and <classname
Goik Martin's avatar
Goik Martin committed
      xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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
Goik Martin's avatar
Goik Martin committed
                  xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/text/NumberFormat.html">NumberFormat</classname>
                  documentation and its <methodname
Goik Martin's avatar
Goik Martin committed
                  xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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
Goik Martin's avatar
Goik Martin committed
                  xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/format/DateTimeFormatter.html">DateTimeFormatter</classname>
                  providing the <methodname
Goik Martin's avatar
Goik Martin committed
                  xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/format/DateTimeFormatter.html#ofLocalizedDate(java.time.format.FormatStyle)">static
                  DateTimeFormatter ofLocalizedDate(FormatStyle
                  dateStyle)</methodname> method. Then read about class
                  <classname
Goik Martin's avatar
Goik Martin committed
                  xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/format/FormatStyle.html">FormatStyle</classname>
                  and the <methodname
Goik Martin's avatar
Goik Martin committed
                  xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/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>

    <figure xml:id="sd1_numbers_fig_polymorphicNumberParsing">
      <title>Polymorphic number parsing</title>

      <programlisting language="java">final NumberFormat de = NumberFormat.getInstance(Locale.GERMANY),
                       us = NumberFormat.getInstance(Locale.US);
try {
  final Number[] values = {
    de.parse("103.234"), de.parse("400.000,234"),
    us.parse("103.234"), us.parse("400.000,234"),};
  for (final Number n: values) {
    System.out.println(n + "(" + n.getClass().getTypeName() + ")");
  } catch (ParseException e) { ... }</programlisting>
      <screen>103234(java.lang.Long)
400000.234(java.lang.Double)
103.234(java.lang.Double)
400(java.lang.Long)</screen>
    </figure>
  </section>

  <section xml:id="sd1_numbers_sect_WorkingwithMoney">
    <title>Working with Money</title>

    <figure xml:id="sd1_numbers_fig_floatLimitedPreceision">
      <title>Limited <code language="java">float</code> precision</title>

      <programlisting language="java">final float result = 0.99f - 0.1f -0.1f -0.1f;
System.out.println(result);</programlisting>

      <screen>0.68999994</screen>
    </figure>

    <figure xml:id="sd1_numbers_fig_doubleLimitedPreceision">
      <title>Limited <code language="java">double</code> precision</title>

      <programlisting language="java">final double result = 0.99 - 0.1 -0.1 -0.1;
System.out.println(result);</programlisting>

      <screen>0.6900000000000001</screen>
    </figure>

    <figure xml:id="sd1_numbers_fig_usingBigDecimal">
      <title>Using <classname
Goik Martin's avatar
Goik Martin committed
      xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/math/BigDecimal.html">BigDecimal</classname></title>

      <programlisting language="java">final BigDecimal zero_dot_99 = new BigDecimal("0.99");
final BigDecimal zero_dot_1 = new BigDecimal("0.1");

BigDecimal 
  result = zero_dot_99.subtract(zero_dot_1);  // Subtracting 0.1

  result = result.subtract(zero_dot_1);       // Subtracting 0.1
  result = result.subtract(zero_dot_1);       // Subtracting 0.1

System.out.println(result);</programlisting>

      <screen>0.69</screen>
    </figure>

    <figure xml:id="sd1_numbers_fig_usingBigDecimalChaining">
      <title>Chaining <classname
      xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/math/BigDecimal.html">BigDecimal</classname>
      operations</title>

      <programlisting language="java">final BigDecimal zero_dot_99 = new BigDecimal("0.99");
final BigDecimal zero_dot_1 = new BigDecimal("0.1");