Loss of accuracy with large values - java

I am having a problem with large values.
Please help me.
Scanner scanner=new Scanner(System.in);
double rate=1.0000;
double value=scanner.nextDouble();
value*=rate;
BigDecimal bigDecimal=new BigDecimal(value);
System.out.println(bigDecimal);
But when I enter the input as
121212121212121212121212121212121212121212121212
My output is
121212121212121209445819616146456785067331026944
Please help me.
How can I get values accurately?

There's no point in using BigDecimal if you are initializing it with a double, which has a limited precision.
You should initialize it with a String instead :
Scanner scanner=new Scanner(System.in);
String value=scanner.nextLine();
BigDecimal bigDecimal=new BigDecimal(value);
System.out.println(bigDecimal);
If you wish to multiple your input by a value other than 1 (multiplying by 1 is pointless), use bigDecimal.multiply(...).

Related

Bigdecimal userinput or double to Bigdecimal

I am creating a Currency converter using BigDecimal and now I am suck with an issue.
I have a user-defined number - "Amount" (this is the amount of currency you want to convert)
I am putting that userValue through the scanner class but I have only ever done this successfully with the following :
int userInput = new scanner.nextint();
I would have loved userinput to be passed as a BigDecimal
but my understanding of java is very limited.
would you suggest converting the double to BigDecimal or is there a much simple way.
If you would like to get user input as a BigDecimal then you can use one of Scanner class method nextBigDecimal() To convert existing double to BigDecimal you can use BigDecimal.valueOf() method.
Code sample:
public static void main(String[] args) {
var scanner = new Scanner(System.in);
System.out.println("Enter BigDecimal");
var number = scanner.nextBigDecimal();
System.out.println("BigDecimal from user input: " + number);
var doubleNumber = 2.15;
var decimal = BigDecimal.valueOf(doubleNumber);
System.out.println("Double converted to BigDecimal: " + decimal);
}
Listing:
Enter BigDecimal
2,15
BigDecimal from user input: 2.15
Double converted to BigDecimal: 2.15
Process finished with exit code 0
Keep in mind that while converting double to BigDecimal you may loose some accuracy of data, because double is less accurate comparing to BigDecimal.

Restrict user to input only numbers(int, float, double)

A user has to input only numbers(int, float, double) into an ArrayList. If a user inputs anything but numbers, an exception InputMismatchException must be thrown.
I thought of using Number class.
Scanner input = new Scanner(System.in);
ArrayList<Number> number = new ArrayList<Number>();
System.out.println("Enter number");
(data_type???) number_var = input.??????;
number.add(number_var);
This code will be in do while asking user if he/she wants to continue to give input or not. The only problem is how to restrict user to give input as only numbers. This should be done without creating another class but a method is allowed to restrict user.
You could just accept all numbers as doubles. Ints and floats could be converted to doulbles seemlesly:
Scanner input = new Scanner(System.in);
List<Double> number = new ArrayList<Double>();
System.out.println("Enter number");
number.add(input.nextDouble());
The docs for Scanner should describe what you need. Your scanner can read input as any kind of number that you want. If the input doesn't match what you are expecting it will throw the InputMismatchException.

Program crashes when given high values

My coding, im trying to make a program that wont crash whatever the input is from user, the program will divide and print out the answer. i have searched but could not find any help!
The coding works fine for numbers smaller than 100000000 or 199999999 you get the point.
Scanner in = new Scanner(System.in);
double n1 = in.nextInt();
double n2 = in.nextInt();
double n3 = n1/n2;
System.out.println(n3);
You are using in.nextInt() which will read an integer whose value less than 2^31 -1 (of course it gets converted to double). But when you give values more than (2^31) - 1 like 12589691475, nextInt() can not read them as they are very big numbers.
Use in.nextDouble() instead.
Use
in.nextDouble();
or
in.nextLong();
For arbitrary big numbers, use java.math.BigInteger or java.math.BigDecimal.
Scanner in = new Scanner(System.in);
BigInteger n1 = new BigInteger(in.nextLine());
BigInteger n2 = new BigInteger(in.nextLine());
BigInteger n3 = n1.divide(n2);
System.out.println(n3);

Read an input of trillions value?

I want to know how to read a number from 1 to trillions in My Java application without an error.
This is the part of my code:
Scanner sc = new Scanner(System.in);
System.out.print("Enter your money value : ");
long value = sc.nextInt();
System.out.print("Your money in String : "+value);
If I enter a value from about 1 to 2.111.111.999 it works fine but
every time I run it and enter greater than that, there's this error message :
Exception in thread "main" java.util.InputMismatchException: For input string: "1000000000000"
at java.util.Scanner.nextInt(Scanner.java:2097)
at java.util.Scanner.nextInt(Scanner.java:2050)
at konversiangka.Konversiangka.main(Konversiangka.java:28)
Java Result: 1
I guess this is a "data type" mistake.
I know if you want to store a trillion in a long data type you have to add "L" in the end
of the value, like this, "1000000000000L". But I don't want User to add that when they enter a value on the program,
So can you help Me how to do that?
I Appreciate any suggestion and correction, thanks.
Use
long value = sc.nextLong();
instead.
The reason for the error is that the maximum value that can be put into an int is 2,147,483,647, and even though you declared the variable as a long, Scanner.nextInt() always tries to convert the number into an int.
You can use a long as Tharwen mentioned or you can use java.math.BigDecimal. BigDecimal is a class made for holding a decimal number as big (or small) as you want. You can see all the primitive data types and their max/min size here http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
Scanner sc = new Scanner(System.in);
System.out.print("Enter your money value : ");
BigDecimal value = sc.nextBigDecimal();
System.out.print("Your money in String : "+value);
Output:
Enter your money value : 271075217301782039710237102710521231.23
Your money in String : 271075217301782039710237102710521231.23

Java double input

I am trying to let the user freedom of entering a number at his own style like he can choose to enter 2 or 2.00 but as you know the double cannot accept this (2). i want the double to accept this with 2 decimal places only (basically i am representing money).
this is what i am not sure how to take the input and convert that in to the 2decimals format. New to java.tks
Tried google but cant find where i can format at the input itself, means dont even let the user type any more decimal places other than 2decimal places, not post-process after entered in to multiple different variables., tks
public static void add()
{
double accbal;
Scanner sc = new Scanner(System.in);
DecimalFormat df = new DecimalFormat("0.00");
System.out.println("Enter account balance");
accbal = sc.nextDouble();
//this is the part where i need to know the entered value is formated to only 2 decimal places
}
Since showing decimal places is really a formality to the end user, you could read your value in as a String instead and convert it to a Double or BigDecimal, the latter being preferred if you're working with actual finances.
Related: What Every Computer Scientist Should Know About Floating-Point Arithmetic
public static void add() {
BigDecimal accbal; // could declare a Decimal
Scanner sc = new Scanner(System.in);
DecimalFormat df = new DecimalFormat("#.00");
System.out.println("Enter account balance");
accbal = new BigDecimal(sc.nextLine());
System.out.println(df.format(accbal.doubleValue()));
}
Try this:
DecimalFormat df = new DecimalFormat ("#.##");//format to 2 places
accbal = sc.nextDouble();
System.out.print(df.format(aacbal));//prints double formatted to 2 places
however I see you say:
Tried google but cant find where i can format at the input itself,
means dont even let the user type any more decimal places other than
2decimal places
If the above is your intention for whatever reason then simply read in the input using nextLine() and then check to make sure after the decimal point it only has a length of 2:
double accbal=0;
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("Enter account balance");
String s = sc.nextLine();
if (s.substring(s.indexOf('.') + 1).length() <= 2)//accept input and convert to double
{
accbal = Double.parseDouble(s);
break; //terminates while loop
} else {
System.out.println("Incorrect input given! Decimal places cant exceed 2");
}
}
System.out.println("Balance: "+accbal);
If you want to accept input of the form "#.##" just specify a custom regex for Scanner.hasNext :-)
final Scanner input = new Scanner(System.in);
final Pattern pattern = Pattern.compile("\\d+\\.\\d{2}?");
while (input.hasNext()) {
System.out.println((input.hasNext(pattern) ? "good" : "bad")
+ ": " + input.nextDouble());
}
Using the following input:
2.00
3.14159
2
The result is: (also found here)
good: 2.0
bad: 3.14159
bad: 2.0
This way allows you to verify they enter an amount with two decimal places.
Even though you said you do not want a mere post-processing solution, in case you already have an amount and wish to convert it to use 2 decimal places, and you're focused on precision (since this is money), maybe try using BigDecimal -- in particular, see BigDecimal.setScale:
while (input.hasNextBigDecimal()) {
System.out.println(input.nextBigDecimal().setScale(2, RoundingMode.HALF_UP));
}
The output is thus:
2.00
3.14
2.00

Categories