• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Bear Bibeault
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • Tim Cooke
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Stephan van Hulst
  • Jj Roberts
  • Carey Brown
Bartenders:
  • salvin francis
  • Frits Walraven
  • Piet Souris

BigDecimal compareTo and try catch block

 
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Please see the following code that compares bigDecimal objects:



Please assist me with the following:

1. Why is it that if I enter 99.99, it enters the if loop and prints "Please enter a valid number". 99.99 is not greater than 99.99.
2. I am new to try catch blocks. I see that they have block scope. Lines 18 and 24 are duplicated, as it appears I have to check the code inside the try block and then duplicate the code outside the try catch block because that is what I want to do. Is this the correct way to do it?

Thank you.
 
Bartender
Posts: 2235
63
IntelliJ IDE Firefox Browser Spring Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Welcome to the Ranch!

Jay Rex wrote:1. Why is it that if I enter 99.99, it enters the if loop and prints "Please enter a valid number". 99.99 is not greater than 99.99.


Read carefully what condition you have in line 25. Write on pensil your calculation for input 99.99.

Jay Rex wrote:2. I am new to try catch blocks. I see that they have block scope. Lines 18 and 24 are duplicated, as it appears I have to check the code inside the try block and then duplicate the code outside the try catch block because that is what I want to do. Is this the correct way to do it?


It is not the correct way. If no exception is thrown then the value of result will aleady br set to desired value. No need to duplicate this. In this case the computation will be quick so no harm done, but if it were an expensive operation you might have a problem.

Also, I noticed that you use BigDecimal(double) constructor. Read the warning in corresponding javadoc so you are not surprised in the future.
 
Marshal
Posts: 71722
312
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Welcome to the Ranch

Don't use next() and try doing converting the result. Use next() when you want to get one token and use it as text. If you want a BigDecimal from a Scanner, that is what you should ask for: look here.

Don't use both > and <. Try != instead. [edit] That bit is there because I misread your original post. Sorry.
 
Rancher
Posts: 4786
50
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paweł Baczyński wrote:
Read carefully what condition you have in line 25. Write on pensil your calculation for input 99.99.


That check is correct as far as I can see.

Paweł Baczyński wrote:
Also, I noticed that you use BigDecimal(double) constructor. Read the warning in corresponding javadoc so you are not surprised in the future.



This, though, is the cause of point (1).
 
Sheriff
Posts: 7111
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If you're still stumped, try printing the values of upperLimit and lowerLimit.
 
Jay Rex
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paweł Baczyński wrote:Welcome to the Ranch!


Thank you for the welcome

Paweł Baczyński wrote:It is not the correct way. If no exception is thrown then the value of result will already be set to desired value. No need to duplicate this. In this case the computation will be quick so no harm done, but if it were an expensive operation you might have a problem.


The code has been corrected.

Campbell Ritchie wrote:Welcome to the Ranch


Thank you for the welcome

Campbell Ritchie wrote:Don't use next() and try doing converting the result. Use next() when you want to get one token and use it as text. If you want a BigDecimal from a Scanner, that is what you should ask for: look here.



I am trying to accept input from the user and if the input is not a valid number, it needs to throw an exception and exit. Is there a more efficient way to do that?

Dave Tolls wrote:This, though, is the cause of point (1).


Thank you.

Knute Snortum wrote:If you're still stumped, try printing the values of upperLimit and lowerLimit.






 
Jay Rex
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you for all the help. My code has reduced to the following:

 
Jay Rex
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
My attempt at nextBigDecimal didn't work, so the following code works, but still uses next():

 
Paweł Baczyński
Bartender
Posts: 2235
63
IntelliJ IDE Firefox Browser Spring Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Dave Tolls wrote:That check is correct as far as I can see.



It looks like it is. My bad.
 
Campbell Ritchie
Marshal
Posts: 71722
312
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Who needs an exception? The three exceptions you are likely to see are NoSuchElementException (NSEE) IllegalStateException (ISE) and InputMismatchException (IME). You can avoid NSEE and ISE by not closing the Scanner, nor closing System.in with ctrl‑D or ctrl‑Z. But you already know not to close such objects. A long time ago, Rob Spoor taught me that you can avoid an IME with a simple loop:-Ideally, that loop belongs in a method in a utility class, but you probably haven't got enough time to write a utility class now. The loop makes sure anything not matching the required pattern will simply be rejected, so no risk of an IME.Goodbye, try and goodbye, catch. Also goodbye, rounding; you don't need to round anything. It will cope with input like 123456789.012345678901234567890123456789 quite happily.
Avoid System.exit. It won't do any harm in a simple app like this, but it can do serious damage in multi‑threaded programs.
 
Knute Snortum
Sheriff
Posts: 7111
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It looks like you still have the problem of rounding your input but not your upper and lower limits.
 
Campbell Ritchie
Marshal
Posts: 71722
312
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Do you need new BigDecimal("0") when you can use this?
 
Jay Rex
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Who needs an exception?


Superb answer, thank you. I've implemented that code.

Campbell Ritchie wrote:Avoid System.exit


Noted, thank you.

Knute Snortum wrote:It looks like you still have the problem of rounding your input but not your upper and lower limits.


For this small program, rounding the input is appropriate.

Campbell Ritchie wrote:Do you need new BigDecimal("0") when you can use this?


Thank you again Implemented.

The following code doesn't work, but I want to try and condense the logic further by doing the following:



How do I correct this:



so that it returns a boolean?
 
Campbell Ritchie
Marshal
Posts: 71722
312
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jay Rex wrote:. . . The following code doesn't work, but I want to try and condense the logic further by doing the following:

. . .

You are comparing a boolean from a hasNextXXX() method to a BigDecimal from the nextXXX() method; that won't compile.You need to compare nextBigDecimal() against the limits. So you change it to this:-. . . and it will compile. I am keeping quiet about the serious error hidden in that code, however.

You do need a utility class after all.You will need to add documentation comments, correct my spellling, and create methods for other values, e.g. nextInt(). Beware of nextLine() which needs some additional tweaking. Consider overloading methods to take customised error messages a parameters.

Now: overload those methods to return only values in a particular range. I think that will sort out your problem. Such ranges will be faster to achieve for primitives, e.g. ints, because you can simply use > and <.
 
Knute Snortum
Sheriff
Posts: 7111
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jay Rex wrote:Why is it that if I enter 99.99, it enters the if loop and prints "Please enter a valid number". 99.99 is not greater than 99.99.  


Knute Snortum wrote:If you're still stumped, try printing the values of upperLimit and lowerLimit.


Jay Rex wrote:


Knute Snortum wrote:It looks like you still have the problem of rounding your input but not your upper and lower limits.


Jay Rex wrote:For this small program, rounding the input is appropriate.  


I'm not sure what the length of you program has to do with it, but not rounding the upper and lower limit causes the problem you originally asked about.
 
Campbell Ritchie
Marshal
Posts: 71722
312
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I would prefer to use the BigDecimal(String) constructor or maybe BigDecimal#valueOf().
 
Jay Rex
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Knute Snortum wrote:I'm not sure what the length of you program has to do with it, but not rounding the upper and lower limit causes the problem you originally asked about.


I used Campbell Ritchie's suggestion to use the String constructor instead, which has worked.

Campbell Ritchie wrote:Rob Spoor taught me that you can avoid an IME with a simple loop:-


Unfortunately, the loop doesn't work. It only works for int input, not for floating point input.



Example: 1 passes the while loop, but 1.1 does not pass. If I type hello or 1.1, it has the same result, which is to ask for input again.

 
Knute Snortum
Sheriff
Posts: 7111
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hmm.. it works for me.  Are you using it like this?
 
Campbell Ritchie
Marshal
Posts: 71722
312
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jay Rex wrote:. . . Unfortunately, the loop doesn't work. It only works for int input, not for floating point input.  . . .

I can see nothing wrong with your loop. Unless you live somewhere not using a full stop as the decimal point. Please give us the full details of what goes wrong.
 
Jay Rex
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Knute Snortum wrote:Hmm.. it works for me.  Are you using it like this?


Thank you for your code example. I coped your code verbatim. It compiles but has the same problem that I'm currently experiencing. Please see below.

Campbell Ritchie wrote:I can see nothing wrong with your loop. Unless you live somewhere not using a full stop as the decimal point. Please give us the full details of what goes wrong.


I live in a place where the full stop is the decimal point.

Here is the command line printout:
                                       
 
Jay Rex
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This seems to be a locale issue, as the decimal works if I enter a comma, which is not correct for where I live, nor is it correct in terms of the code I submitted at the beginning of this thread which didn't include hasNextBigDecimal().


 
Campbell Ritchie
Marshal
Posts: 71722
312
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It does sound like a locale issue, which is why the full stop didn't help. Try System.out.println(Locale.getDefault());
 
Jay Rex
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:It does sound like a locale issue, which is why the full stop didn't help.



The problem is not with System.out.println(). That prints the correct value with a full stop. The problem is that when I introduced !keyboardInput.hasNextBigDecimal(), it no longer recognised the full stop as a decimal place.

The output is correct, but only if I use a comma. It is as if hasNextBigDecimal() ignores my locale, but then System.out.println() gets it right again.
 
Campbell Ritchie
Marshal
Posts: 71722
312
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
but what did you get when you printed your Locale?
 
Jay Rex
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It prints the correct locale for my country.
 
Campbell Ritchie
Marshal
Posts: 71722
312
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Where's that? Is it somewhere where people speak several languages?
 
Jay Rex
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The Locale is en_ZA.

The locale uses the period as the decimal point.
 
Campbell Ritchie
Marshal
Posts: 71722
312
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes, I think en_ZA should use full stop. Maybe it would use comma if you went into Afrikaans or Xhosa or similar.
Don't declare IOException; that code doesn't throw such an Exception.
I tried your code unchanged, but without the IOException, ad got this:-I am using en_GB (or maybe en_UK) as my locale. Try changing the Locale on your system. I tried using System.getProperties orsimilar to print oiut informaton about my installation and got the following:

java PropertiesList
The property awt.toolkit   . . .
The property user.country                   is GB
. . .
The property user.language                  is en
. . .

So you can work out the locale from that. Try moving your Locale: System.setProperty("user.country", "GB"); System.setProperty("user.language", "en");
See whether that makes any difference.
 
Jay Rex
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Doesn't this constitute a bug in the JVM, if the locale is not adhered to?

According to the locale on my system, it is en_ZA.

It shouldn't matter what language I use, as the locale is defined for the country, not the language.

Changing the locale fixes the problem, but I don't live in the states, or anywhere else. It needs to honour my existing locale.

Should I submit this as a bug?
 
Saloon Keeper
Posts: 12622
273
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's probably not.

Please assign Locale.getDefault(Locale.Category.FORMAT) to a variable locale and print it, as well as DecimalFormatSymbols.getInstance(locale).getDecimalSeparator().
 
Jay Rex
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:It's probably not.



The code:


The output:


Further investigation:

https://www.sadev.co.za/content/how-correctly-format-currency-south-africa

I have never seen this in practice, anywhere, ever.

So, learning Java has taught me something I never knew about my own country.

Is the best way forward, for me to add the following to my code?

 
Stephan van Hulst
Saloon Keeper
Posts: 12622
273
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It depends. If you want to use the user's native formatting, then no, just use the default.

If you want to use the same format regardless of the user's locale, use the root locale, which is not specific to any culture (although most of its settings are the same as the English locale). Even so, don't override the default locale. Just configure your scanner properly:
 
Campbell Ritchie
Marshal
Posts: 71722
312
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I had quite forgotten that you can set a Locale for a Scanner; it is worth getting the Locale and viewing it with myScanner.locale(). Note that Scanner has different names for its getXXX and setXXX methods from everybody else.
 
Campbell Ritchie
Marshal
Posts: 71722
312
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I enhanced your code to change Locale:-Note that plain simple %f defaults to six places after the decimal point.
 
Jay Rex
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you for all the help. This has been most enlightening.
 
Campbell Ritchie
Marshal
Posts: 71722
312
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That's a pleasure Interesting problem.
 
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
For Query 1: The problem is that the number 99.99 can't be represented exactly as a double, so it is represented by closet double value. Unfortunately, which is not much closer to 99.99. e.g The same problem you would found when you to see the output of the  statement System.out.println(2.00-1.10);. The best solution you already got in above discussion that always use the BigDecimal(String) constructor instead of BigDecimal(Double).

For Query 2: You can simplify the code as like below in the try catch block:
try {
           result = new BigDecimal(input).setScale(decimalPlaces, RoundingMode.HALF_UP);
           if (result.compareTo(upperLimit) > 0 || result.compareTo(lowerLimit) < 0) {
               System.out.println("Please enter a valid number.");
               System.exit(0);
           }
           else {
               System.out.println("The number entered: " + result);
           }
       }
       catch(Exception e) {
           System.out.println("Please enter a valid number.");
           System.exit(0);
       }

 
Knute Snortum
Sheriff
Posts: 7111
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Welcome to the Ranch, Sthir Vidyut!

Thank you for attempting to UseCodeTags (that's a link).  However, you need to insert your code in between tags or it doesn't work.  To make sure you've got it right, use the Preview button, right next to the Submit button.
 
To avoid criticism do nothing, say nothing, be nothing. -Elbert Hubbard. Please critique this tiny ad:
Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop
https://coderanch.com/wiki/718759/books/Building-World-Backyard-Paul-Wheaton
reply
    Bookmark Topic Watch Topic
  • New Topic