I am attempting to ask for a value and tax rate and multiple those together to get a amount owed. It works great if I use whole numbers but it will not work when using decimals.
package apples;
import javax.swing.JOptionPane;
class apples {
public static void main(String[] args) {
String fn = JOptionPane.showInputDialog("Enter assessment value");
String sn = JOptionPane.showInputDialog("Enter local tax rate");
int num1 = Integer.parseInt(fn);
int num2 = Integer.parseInt(sn);
int sum = num1 * num2;
JOptionPane.showMessageDialog(null, "Tax amount" +sum);
}
}
I expected it to multiple .23 by the value entered but I get this.
Exception in thread "main" java.lang.NumberFormatException: For input string: ".23"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:654)
at java.base/java.lang.Integer.parseInt(Integer.java:786)
at apples.apples.main(apples.java:11)
The best data type to use for storing an amount of money is BigDecimal. It lets you do calculations with decimal amounts, without introducing floating point errors. It also keeps track of the precision of any number, which is useful for precise calculations.
If you try to use float or double instead of BigDecimal, small errors can creep into your calculations, which can cause problems when you try to compare values, or print values. There are some really good explanations of why this happens in the answers to this question so it's important to be aware of this.
You can easily change your code to use the BigDecimal class in place of Integer, except that you have to use methods (like add and multiply) instead of operators (like + and *). You might end up with something like this.
public static void main(String[] args) {
String assessmentValueString = JOptionPane.showInputDialog("Enter assessment value");
String taxRateString = JOptionPane.showInputDialog("Enter local tax rate");
BigDecimal assessmentValue = new BigDecimal(assessmentValueString);
BigDecimal taxRate = new BigDecimal(taxRateString);
BigDecimal totalTax = assessmentValue.multiply(taxRate);
JOptionPane.showMessageDialog(null, "Tax amount" + totalTax);
}
You may want the last calculation to be rounded to two decimal places, regardless of the amounts that are entered. You can do that like this.
MathContext twoDecimals = new MathContext(2);
BigDecimal totalTax = assessmentValue.multiply(taxRate, twoDecimals);
In your case, I would use a float since you don't want whole numbers but floating point numbers.
Instead of:
int num1 = Integer.parseInt(fn);
you would do:
float num1 = Float.parseFloat(fn);
So your sum variable also has to be a float.
A float is just a float point number that has a precision of 6-7 decimals. Should be more than enough for tax rate.
Related
This is my code for a school assignment. I was supposed to create code that could calculate the square root of any number using Newton's method and starting guess. It was working correctly when the epsilon was 0.0001 however I was asked to make it more precise. When changed to 0.00000001 (requested by my teacher) it infinitely loops because it is repeatedly giving an answer that does is not within 0.00000001 the target number when multiplied by itself, and all further calculations yield the same result.
import java.lang.Math.*;
public class main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the number you are trying to find the square root of");
Float input1 = sc.nextFloat();
Scanner sc2 = new Scanner(System.in);
System.out.println("Provide a guess to start");
Float input2 = sc2.nextFloat();
calc(input1, input2);
}
static void calc(Float input1, Float input2) {
final double epsilon = 0.00000001;
float sqr = (input1/input2 + input2)/2;
do{
sqr = (input1/input2 + input2)/2;
input2 = sqr;
} while (Math.abs(sqr * sqr - input1)>epsilon);
System.out.println("The square root of " + input1 + " is " + sqr);
}}
Floating point numbers only have a limited precision.
The significant concept is the unit of least precision, or ULP. This is the amount the number varies by if you waggle its least significant bit.
This changes depending on the number you're starting from; but for 1.0f, the ULP is 1.1920929E-7. (You can find this using the Math.ulp method). So, assuming you're trying to find something a better solution from something of the order 1, using float, you can't get within 1e-8 of it.
Use double instead: you still have limited precision, but the ULP is much smaller: 2.2e-16.
I've been trying to make the unitTotal(double) into an integer by using the rounding method, then assigning the integer to the mark variable. I have been stuck on this question and I don't know what I'm doing wrong. If anyone can explain to me what I'm doing wrong it'd be appreciated. Thank you
public class GradeCalculator {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double unitTotal;
int mark;
String grade;
System.out.println("Enter your unit total score");
unitTotal = sc.nextDouble();
Math.round(unitTotal);
mark = unitTotal;
You should assign the rounding result to the variable:
mark = (int) Math.round(unitTotal);
Do note that Math class suggests to round double to long. By casting to int you are potentially loosing precision.
You could use sc.nextFloat(); instead. Then you can use Math.round(float a) that returns int and assign it to mark:
mark = Math.round(sc.nextFloat());
If what you want is a method for rounding a double to the nearest whole number then I have an idea, though it's not using a library method.
public int round(double value) {
int cutDecimals = (int) value; // This cuts the decimals entirely, rounding down
double decimals = value - ((double) cutDecimals); // Gives only the decimals
if(decimals < 0.5) return cutDecimals; // If the decimals is less than 0.5 we return the rounded down number
else return cutDecimals + 1; // If the decimals is over 0.5 we round up
}
According to Docs, Math.round method returns long when passing value is double and returns int when passing value is float.
Change type of mark to long or you need to convert long into int manually. Keep in mind that it could throw an exception if return value is more than Integer.MAX_VALUE.
Also, you need to store return value into variable.
Math.round(unitTotal);
replace with
mark = Math.round(unitTotal);
HTH.
(COMPLETE newbie here).
I've got an extra sheet with simple exercises to complete. One of the exercises says to write a program where user can input a random amount of money and the program tells the user how many euros, 50 cents, 20 cents, 10 cents, 5 cents, 2 cents and 1 cents are needed to make up the amount entered.
I try to use the modulus to get the amount of cents needed,
My question is how do I get my program to calculate the number of CENTS needed?
Everytime I use division operator to get the number of 50 cents needed on the remainder of the amount (ex. 0.60) it rounds the double up giving me 2 as output.
Scanner keyboard = new Scanner(System.in);
System.out.print("Input money recieved: ");
double recieve = keyboard.nextDouble();
double cents = recieve * 100;
int centsTotal = (int)cents;
System.out.print("Cents in total " + centsTotal);
int notes = centsTotal / 100;
System.out.print("\nEuros: " + notes);
double remain = recieve % notes;
System.out.printf("\nRemain: %.2f",remain);
double remain2 = remain / 0.5;
System.out.println("\nTest: ",remain2);
My output is:
Input money recieved: 45,78
Cents in total 4578
Euros: 45
Remain: 0,78
Test: 1.5600000000000023
You can cheat by using the Math.round() function like so:
double roundOff = Math.round(valueToRound * 100.0) / 100.0;
This ensures that you keep the value as a double, which allows you to do further operations on it if necessary.
One way is maybe a little brutal, but memory efficient (create no new object or variables). Simply cast your double to int to round down.
public class RoundingTest {
public static void main(String[] args) {
double num = 1.56;
System.out.println("Test: " + (int)num);
}
}
Outputs:
Test: 1
This also allows you to keep your original double untouched for further calculation if needed.
import java.util.*;
public class Investment
{
public static int years=0;
public static void main(String[] args)
{
Scanner kbd = new Scanner(System.in);
System.out.println("Please enter an integer representing the whole dollar value of your initial investment: $");
int startBal=kbd.nextInt();
System.out.println("Please enter the whole number percentage, excluding the percent sign, of the interest rate on the investment.");
int interestRate=kbd.nextInt()/100;
int endBal=startBal*2;
int currentBal=startBal;
while (endBal>=currentBal)
{
currentBal=currentBal*interestRate+currentBal;
years++;
}
System.out.println("It will take "+years+" years to double your investment.");
}
}
The output I'm seeing is:
Please enter an integer representing the whole dollar value of your initial investment: $
10000
Please enter the whole number percentage, excluding the percent sign, of the interest rate on the investment.
5
The "10000" and "5" are my input. The program should be printing my final statement with the answer "15," but instead doesn't do anything, and doesn't terminate.
int interestRate=kbd.nextInt()/100;
Since interestRate is an int, it gets rounded down to zero.
So this line:
currentBal=currentBal*interestRate+currentBal;
resolves to:
=> currentBal=currentBal*0+currentBal;
=> currentBal=0+currentBal;
=> currentBal=currentBal;
So the value never increases, so will never reach double its initial value, so infinite loop.
You would have to replace the line with:
double interestRate=kbd.nextInt()/100.0;
Your interestRate is declared as an int so it will be set to 0.
You should declare all values as doubles, since we-re talking about money we want to be precise :)
You have an int interest rate, which when divided by 100, becomes 0. Make it a double and use the double literal 100.0 to divide, to force floating-point division.
double interestRate=kbd.nextInt()/100.0;
The currentVal variable will need to be a double also.
My output with the changes:
Please enter an integer representing the whole dollar value of your initial investment: $
10000
Please enter the whole number percentage, excluding the percent sign, of the interest rate on the investment.
5
It will take 15 years to double your investment.
This will let the program finish. But normally it's not a good idea to use a double to store money.
Your doing integer division 5/100 which = 0 remainder 5. So in your calculation you are multiplying by 0 so your current balance will always be 0 and never reach end balance. Try using a double for your interest rate rather than an integer.
while (endBal>=currentBal)
{
currentBal=currentBal*interestRate+currentBal;
years++;
}
of course it never terminate, you are only incrementing years but the variables on the while are endBal and currentBal
My coworker did this experiment:
public class DoubleDemo {
public static void main(String[] args) {
double a = 1.435;
double b = 1.43;
double c = a - b;
System.out.println(c);
}
}
For this first-grade operation I expected this output:
0.005
But unexpectedly the output was:
0.0050000000000001155
Why does double fails in such a simple operation? And if double is not the datatype for this work, what should I use?
double is internally stored as a fraction in binary -- like 1/4 + 1/8 + 1/16 + ...
The value 0.005 -- or the value 1.435 -- cannot be stored as an exact fraction in binary, so double cannot store the exact value 0.005, and the subtracted value isn't quite exact.
If you care about precise decimal arithmetic, use BigDecimal.
You may also find this article useful reading.
double and float are not exactly real numbers.
There are infinite number of real numbers in any range, but only finite number of bits to represent them! for this reason, rounding errors is expected for double and floats.
The number you get is the closest number possible that can be represented by double in floating point representation.
For more details, you might want to read this article [warning: might be high-level].
You might want to use BigDecimal to get exactly a decimal number [but you will again encounter rounding errors when you try to get 1/3].
Yes it worked this way using BigDecimal operations
private static void subtractUsingBigDecimalOperation(double a, double b) {
BigDecimal c = BigDecimal.valueOf(a).subtract(BigDecimal.valueOf(b));
System.out.println(c);
}
double and float arithmetic are never going to be exactly correct because of the rounding that occurs "under the hood".
Essentially doubles and floats can have an infinite amount of decimals but in memory they must be represented by some real number of bits. So when you do this decimal arithmetic a rounding procedure occurs and is often off by a very small amount if you take all of the decimals into account.
As suggested earlier, if you need completely exact values then use BigDecimal which stores its values differently. Here's the API
public class BigDecimalExample {
public static void main(String args[]) throws IOException {
//floating point calculation
double amount1 = 2.15;
double amount2 = 1.10;
System.out.println("difference between 2.15 and 1.0 using double is: " + (amount1 - amount2));
//Use BigDecimal for financial calculation
BigDecimal amount3 = new BigDecimal("2.15");
BigDecimal amount4 = new BigDecimal("1.10") ;
System.out.println("difference between 2.15 and 1.0 using BigDecimal is: " + (amount3.subtract(amount4)));
}
}
Output:
difference between 2.15 and 1.0 using double is: 1.0499999999999998
difference between 2.15 and 1.0 using BigDecmial is: 1.05
//just try to make a quick example to make b to have the same precision as a has, by using BigDecimal
private double getDesiredPrecision(Double a, Double b){
String[] splitter = a.toString().split("\\.");
splitter[0].length(); // Before Decimal Count
int numDecimals = splitter[1].length(); //After Decimal Count
BigDecimal bBigDecimal = new BigDecimal(b);
bBigDecimal = bBigDecimal.setScale(numDecimals,BigDecimal.ROUND_HALF_EVEN);
return bBigDecimal.doubleValue();
}