Double.parseDouble not accounting for locale [duplicate] - java

I want to convert some numbers which I got as strings into Doubles, but these numbers are not in US standard locale, but in a different one. How can I do that?

Try java.text.NumberFormat. From the Javadocs:
To format a number for a different Locale, specify it in the call to getInstance.
NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
You can also use a NumberFormat to parse numbers:
myNumber = nf.parse(myString);
parse() returns a Number; so to get a double, you must call myNumber.doubleValue():
double myNumber = nf.parse(myString).doubleValue();
Note that parse() will never return null, so this cannot cause a NullPointerException. Instead, parse throws a checked ParseException if it fails.
Edit: I originally said that there was another way to convert to double: cast the result to Double and use unboxing. I thought that since a general-purpose instance of NumberFormat was being used (per the Javadocs for getInstance), it would always return a Double. But DJClayworth points out that the Javadocs for parse(String, ParsePosition) (which is called by parse(String)) say that a Long is returned if possible. Therefore, casting the result to Double is unsafe and should not be tried!
Thanks, DJClayworth!

NumberFormat is the way to go, but you should be aware of its peculiarities which crop up when your data is less than 100% correct.
I found the following usefull:
http://www.ibm.com/developerworks/java/library/j-numberformat/index.html
If your input can be trusted then you don't have to worry about it.

Just learning java and programming. Had similar question. Found something like this in my textbook:
Scanner sc = new Scanner(string);
double number = sc.nextDouble();
The book says that a scanner automatically decodes what's in a String variabel and that the Scanner class automatically adapts to the language of the set Locale, system Locale being the default, but that's easy to set to something else.
I solved my problem this way. Maybe this could work for the above issue instead of parsing?
Addition: The reason I liked this method was the fact that when using swing dialouge boxes for input and then trying to convert the string to double with parse I got a NumberFormatException. It turned out that parse exclusively uses US-number formatting while Scanner can handle all formats. Scanner made the input work flawlessly even with the comma (,) decimal separator. Since the most voted up answer uses parse I really don't see how it would solve this particular problem. You would have to input your numbers in US format and then convert them to your locale format. That's rather inconvenient when ones numeric keybord is fitted with a comma.
Now you're all free to shred me to pieces ;)

You use a NumberFormat. Here is one example, which I think looks correct.

Use NumberFormat.getNumberInstance(Locale)

This should be no problem using java.text.DecimalFormat.

Do you know which locale it is? Then you can use
DecimalFormat format = DecimalFormat.getInstance(theLocale);
format.parse(yourString);
this will even work for scientific notations, strings with percentage signs or strings with currency symbols.

Here is how you use parseDouble to convert a String to a Double:
doubleExample.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class doubleExample {
public static void main(String[] args) {
Double myDouble = new Double("0");
System.out.println("Please enter a number:");
try
{
//get the number from console
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
myDouble = Double.parseDouble(br.readLine());
}
//if invalid value was entered
catch(NumberFormatException ne)
{
System.out.println("Invalid value" + ne);
System.exit(0);
}
catch(IOException ioe)
{
System.out.println("IO Error :" + ioe);
System.exit(0);
}
System.out.println("Double value is " + myDouble);
}
}

Related

Number Format Exception in java but format is true

List<Person> list=new ArrayList<Person>();
public List<Person> readFile(){
File file =new File("dosya.txt");
try {
FileReader fileReader=new FileReader(file);
BufferedReader reader=new BufferedReader(fileReader);
while(reader.readLine()!=null){
String personData= reader.readLine();
System.out.println(personData);
Person person=new Person();
person.setName(personData.substring(1,personData.indexOf("#")));
String sayı=personData.substring(personData.indexOf("#")+1,personData.indexOf("#",personData.indexOf("#")+1));
person.setMoney(Double.valueOf(sayı));
personData=personData.substring(personData.indexOf("#")+1);
System.out.println(personData);
person.setRate(Double.valueOf(personData.substring(0,3)));
personData=personData.substring(personData.indexOf("#")+1);
System.out.println(personData);
person.setNumber(Short.valueOf(personData));
list.add(person);
}
} catch (Exception e) {
e.printStackTrace();
}
This is my code and it seperate "fsyxaimvct wdyeyttuye#1528640,88#0,7#9"
this type of data and it gives mi error like that
java.lang.NumberFormatException: For input string: "2273370,68"
at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.base/java.lang.Double.parseDouble(Double.java:549)
at java.base/java.lang.Double.valueOf(Double.java:512)
at FileProcess.readFile(FileProcess.java:19)
at Main.main(Main.java:7)
Why this cant turn 2273370,68 to double
Double.valueOf() doesn't 'do' locale - it parses specifically only numbers that use . as decimal separator. Your input string contains a comma which means it'll fail.
But, this code is essentially useless. You can't do currency with doubles - doubles are imprecise and will silently round. This is not what you want when working with currency.
The simplest solution is to store the 'atomic unit' for the currency. For dollars, store dollarcents. For bitcoin, store satoshis. For yen, store yen. For english pounds, store pennies. And so on. In a long, or if you must, a BigInteger.
Alternatively, use a library (joda-currency is a good one). You'll often hear advice to use BigDecimal but this is usually a bad idea (it's got all sorts of hairy complications; for example, You can't divide BigDecimals at all unless you really know what you are doing - and it's complicated to write code for them).
Parsing a string with e.g. a euro amount such as "-1234,58" in it can be parsed to the long -123458 using:
Pattern p = Pattern.compile("^(-?)(\\s*\\d*)(?:,(\\d{2}))?$");
var m = p.matcher("2273370,68");
long amount;
if (m.matches()) {
amount =
(m.group(1).equals("-") ? -1L : 1L) * (
100 * (m.group(2).isEmpty() ? 0 : Long.parseLong(m.group(2))) +
(m.group(3) != null ? Long.parseLong(m.group(3)) : 0L));
} else throw new NumberFormatException();
Any attempt to use Double.parseDouble will get you into that rounding trouble and you randomly lose or gain a cent. Run a bank like that and you might get into a wee bit of trouble :)

trouble formatting double in my getter method

my code:
private double retailPrice = 699;
DecimalFormat df = new DecimalFormat("#,###.00");
public double getRetailPrice()
{
return df.format(retailPrice);
}
I am trying to format this for a HW assignment. It's not really required, but I wanted to try this as a learning experience. The method should return a double, but when I try to use decimal formatter, it gives an error:
string cannot be converted into a double
but it's not a string...right?
Basically this ends up as part of a StringBuilder object that is written to a csv file, so it needs to be formatted before it is appended to the StringBuilder.
Do this
public String getRetailPrice()
{
return df.format(retailPrice);
}
You are mixing up two things.
A double number is just that: a number. It does not know about formatting. Formatting is when you turn numbers into strings.
Those are two different things, and there is simply no point in wanting to format a double value whilst keeping it a double. Your code is pointless, plain and simple.
Solution: either have the getter return the double value as it is. Or change its return type to string. And maybe rename it to "getPriceAsFormattedString" for example.
format method return type is String, so you have to parse again formatted value into double. like below
public double getRetailPrice() {
return Double.valueOf(df.format(retailPrice));
}

How to print a string with an int

I am trying to get this code to run and basically solve an equation. So, I asked the user to write an equation. It looked like this:
System.out.println("Write an equation and I will solve for x.");
int answer = in.nextLine();
But I can't get the user to write a string and an int. Do I need to say String answer or int answer?
An int is used when you want the user to enter a number, but here you're looking for a combination of numbers and other characters, so you will need to use a string. When you have the equation stored in a string, you can use other methods to split up the equation into something solvable, then set int answer to whatever the answer comes out to be.
On a simpler side, String will be required input from the user, User will enter the equation.
Then comes the complex part of solving/computing the equation.
1.) create your own parser to pass operands/operator.
2.) Provide a equation with values to some API, you can make use of MVEL or ANTLR
Here's a little program that demonstrates one way to get the equation and divide into numeric / non-numeric values provided the equation input is space delimited. You can then determine what the non-numeric values are and proceed from there.
import java.util.Scanner;
public class SolveX{
public static void main(String[] a){
Scanner in = new Scanner(System.in);
System.out.println("Write an equation and I will solve for x.");
String input = "";
while( in.hasNext() ){
input = in.next();
try{
double d = Double.parseDouble(input);
System.out.println("Double found at: " + input);
// Do what you need to with the numeric value
}
catch(NumberFormatException nfe){
System.out.println("No double found at: " + input);
// Do what you need to with the non numeric value
}
}
}//end main
}//end SolveX class

Comparing doubles' fractions

I'm struggling with the following code which supposed to compare numbers fractions and output some text to user informing him whether the fractions of numbers are the same, i.e.
User inputs two doubles: 3.14 and 4.14
Output: Fractions are the same
User input two double: 3.14 and 4.15
Output: Franctions are not the same
Somehow I've managed to compile the following code but once I tried to run it in Eclipse IDE I came accross the following notifications:
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:909)
at java.util.Scanner.next(Scanner.java:1530)
at java.util.Scanner.nextDouble(Scanner.java:2456)
at comparison.main(comparison.java:12)
import java.util.Scanner;
class comparison
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
double a,b;
a = scan.nextDouble();
b = scan.nextDouble();
compare(a,b);
}
public static void compare(double n, double m)
{
if(n- Math.floor(n) == m - Math.floor(m))
System.out.println("Fractions are the same");
else
System.out.println("Fractions are no the same");
}
}
I would love to obtain any proper explanation of my problems, I guess there are variety of different ways to solve this case in different way but can you please stick with my idea and help me out with this ?
Thanks in advance!
try
Double.toString (n).split ("\\.")[1].equals(Double.toString (m).split ("\\.")[1])
but to fix your problem change to
a = scan.nextDouble();
scan.nextLine (); // consume CR
b = scan.nextDouble();
The documentation for InputMismatchException states:
Thrown by a Scanner to indicate that the token retrieved does not
match the pattern for the expected type, or that the token is out of
range for the expected type.
So, basically, your scanner is trying to get a double, and you apparently entered something that either was not a double or was out of the range of a double.
The best way to handle this would probably be to get Strings from the scanner, and then check to see if they can be converted to doubles. Output an error message if not.
Edit - in agreement with #scary-wombat - use BigDecimal - it has a constructor that takes a String. Be sure to catch NumberFormatException, which will be thrown if what you enter cannot be converted.

how can I parse "30.0" or "30.00" to Integer?

I using:
String str="300.0";
System.out.println(Integer.parseInt(str));
return an exception:
Exception in thread "main" java.lang.NumberFormatException: For input string: "300.0"
How can I parse this String to int?
thanks for help :)
Here's how you do it:
String str = "300.0";
System.out.println((int) Double.parseDouble(str));
The reason you got a NumberFormatException is simply that the string ("300.00", which is a floating point number) could not be parsed as an integer.
It may be worth mentioning, that this solution prints 300 even for input "300.99". To get a proper rounding, you could do
System.out.println(Math.round(Double.parseDouble("300.99"))); // prints 301
I am amazed no one has mentioned BigDecimal.
It's really the best way to convert string of decimal's to int.
Josuha Bloch suggest using this method in one of his puzzlers.
Here is the example run on Ideone.com
class Test {
public static void main(String args[]) {
try {
java.math.BigDecimal v1 = new java.math.BigDecimal("30.0");
java.math.BigDecimal v2 = new java.math.BigDecimal("30.00");
System.out.println("V1: " + v1.intValue() + " V2: " + v2.intValue());
} catch(NumberFormatException npe) {
System.err.println("Wrong format on number");
}
}
}
You should parse it to double first and then cast it to int:
String str="300.0";
System.out.println((int)(Double.parseDouble(str)));
You need to catch NumberFormatExceptions though.
Edit: thanks to Joachim Sauer for the correction.
You can use the Double.parseDouble() method to first cast it to double and afterwards cast the double to int by putting (int) in front of it. You then get the following code:
String str="300.0";
System.out.println((int)Double.parseDouble(str));
Integer.parseInt() has to take a string that's an integer (i.e. no decimal points, even if the number is equivalent to an integer. The exception you're getting there is essentially saying "you've told me this number is an integer, but this string isn't in a valid format for an integer!"
If the number contains a decimal component, then you'll need to use Double.parseDouble(), which will return a double primitive. However, since you're not interested in the decimal component you can safely drop it by just casting the double to an int:
int num = (int)Double.parseDouble(str);
Note however that this will just drop the decimal component, it won't round the number up at all. So casting 1.2, 1.8 or 1.999999 to an int would all give you 1. If you want to round the number that comes back then use Math.round() instead of just casting to an int.

Categories

Resources