Newer
Older
<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/10/docs/api/java/util/Stack.html">Stack</classname>
of integer values</title>
<informaltable border="0">
<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/10/docs/api/java/lang/Object.html#equals(java.lang.Object)">public
xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/Object.html">Object</classname>
obj)</para>
</listitem>
<listitem>
<para><methodname
xlink:href="https://docs.oracle.com/javase/10/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()) {
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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"
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"
iInteger.intValue();</programlisting></td>
</tr>
</informaltable>
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
<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
xlink:href="https://docs.oracle.com/javase/10/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/10/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/10/docs/api/java/lang/Integer.html">Integer</classname>
using the class method <methodname
xlink:href="https://docs.oracle.com/javase/10/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/10/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/10/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">
<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()) {
}</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()) {
}</programlisting></td>
</tr>
</informaltable>
</figure>
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
<qandaset defaultlabel="qanda"
xml:id="sd1_numbers_qanda_boxing_int2Double">
<title>Auto boxing int to Double?</title>
<qandadiv>
<qandaentry>
<question>
<para>Consider the following boxing conversion:</para>
<programlisting language="java">double d = 3.0;
Double dInstance = d;</programlisting>
<para>This code compiles and executes perfectly well. On contrary
the following snippet does not:</para>
<programlisting language="java">int i = 3;
Double dInstance = i;</programlisting>
<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>The compiler will not perform auto boxing from
<code>int</code> do <code>Double</code>. On the other hand Double
is no subtype of Integer disallowing 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">
xlink:href="https://docs.oracle.com/javase/10/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 =
System.out.print("Enter an integer:");
userInput = scanner.nextLine();
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
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
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/10/docs/api/java/util/Scanner.html#nextLine--">Scanner.nextLine()</methodname>
xlink:href="https://docs.oracle.com/javase/10/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/10/docs/api/java/lang/NumberFormatException.html">NumberFormatException</classname>
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
. 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 =
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/10/docs/api/java/lang/Byte.html#parseByte-java.lang.String-">parseByte()</methodname></para>
</listitem>
<listitem>
<para><methodname
xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/Short.html#parseShort-java.lang.String-">parseShort()</methodname></para>
</listitem>
<listitem>
<para><methodname
xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/Integer.html#parseInt-java.lang.String-">parseInt()</methodname></para>
</listitem>
<listitem>
<para><methodname
xlink:href="https://docs.oracle.com/javase/10/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/10/docs/api/java/lang/Float.html#parseFloat-java.lang.String-">parseFloat()</methodname></para>
</listitem>
<listitem>
<para><methodname
xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/Double.html#parseDouble-java.lang.String-">parseDouble()</methodname></para>
</listitem>
<listitem>
<para><methodname
xlink:href="https://docs.oracle.com/javase/10/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/10/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/10/docs/api/java/lang/NumberFormatException.html">NumberFormatException</classname>
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
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/10/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/10/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/10/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>
<figure xml:id="sd1_numbers_fig_locale">
<title>Excerpt from <classname
xlink:href="https://docs.oracle.com/javase/10/docs/api/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
xlink:href="https://docs.oracle.com/javase/10/docs/api/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
xlink:href="https://docs.oracle.com/javase/10/docs/api/java/text/NumberFormat.html">NumberFormat</classname>
<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>
<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
xlink:href="https://docs.oracle.com/javase/10/docs/api/java/util/Locale.html">Locale</classname>
definitions</title>
<qandadiv>
<qandaentry>
<question>
<para>Each <xref linkend="glo_JRE"/> ships with a set of available
<classname
xlink:href="https://docs.oracle.com/javase/10/docs/api/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
xlink:href="https://docs.oracle.com/javase/10/docs/api/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
xlink:href="https://docs.oracle.com/javase/10/docs/api/java/time/LocalDate.html">LocaleDate</classname></title>
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
<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/10/docs/api/java/text/NumberFormat.html">NumberFormat</classname>
xlink:href="https://docs.oracle.com/javase/10/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/10/docs/api/java/time/format/DateTimeFormatter.html">DateTimeFormatter</classname>
xlink:href="https://docs.oracle.com/javase/10/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/10/docs/api/java/time/format/FormatStyle.html">FormatStyle</classname>
xlink:href="https://docs.oracle.com/javase/10/docs/api/java/time/format/DateTimeFormatter.html#withLocale-java.util.Locale-">DateTimeFormatter
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
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);
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>
400000.234(java.lang.Double)
103.234(java.lang.Double)
400(java.lang.Long)</screen>
</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
xlink:href="https://docs.oracle.com/javase/10/docs/api/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).
subtract(zero_dot_1).
subtract(zero_dot_1);
System.out.println(result);</programlisting>
<screen>0.69</screen>
</figure>
<figure xml:id="sd1_numbers_fig_usingBigDecimalFeatures">
<title><classname
xlink:href="https://docs.oracle.com/javase/10/docs/api/java/math/BigDecimal.html">BigDecimal</classname>
features</title>
<itemizedlist>
<listitem>
<para>Higher memory allocation hosting higher precision.</para>
</listitem>
<listitem>
<para>Immutable instances</para>
</listitem>
<listitem>
<para>Calculation performance penalty.</para>
</listitem>
<listitem>
<para>Clumsy interface.</para>
</listitem>
</itemizedlist>
</figure>
</section>
<section xml:id="sd1_numbers_sect_GeneratingRandomNumbers">
<title>Generating Random Numbers</title>
<figure xml:id="sd1_numbers_fig_random">
<title>Using <methodname
xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/Math.html#random--">static
double random()</methodname></title>
<programlisting language="java">for (int i = 0; i < 10; i++) {
System.out.println(Math.random());
}</programlisting>
<screen>0.4754286988826202
0.0060114391743414375
...
0.9047785351372987
0.2516070321935864</screen>
</figure>
<figure xml:id="sd1_numbers_fig_randomSeed">
<title>Seeding a pseudo random generator</title>
<programlisting language="java">try(final Scanner scanner = new Scanner(System.in)) {
System.out.print("Enter an integer seed:");
final long seed = scanner.nextLong();
Random generator = new Random(seed);