This question already has answers here:
Adding and subtracting doubles are giving strange results [duplicate]
(2 answers)
Closed 9 years ago.
Does anyone have an idea where my output problem is?
I have written a Java program, and run it on VM on Mac lion with Eclipse.
Instead of getting 1.41, I got 1.4100000000000001 on my machine.
Example:
Enter the number of quarter: 4
Enter the number of dimes: 3
Enter the number of nickels: 2
Enter the number of pennies: 1
Total $1.4100000000000001
Example:
Enter the number of quarter: 3
Enter the number of dimes: 2
Enter the number of nickels: 1
Enter the number of pennies: 6
Total $1.06
Example:
Enter the number of quarter: 5
Enter the number of dimes: 7
Enter the number of nickels: 4
Enter the number of pennies: 4
Total $2.1900000000000004
It appears sometimes the outputs are correct while other times have an issue.
Code:
import java.util.*;
public class CountChange
{
public static void main(String[]args)
{
Scanner inputScanner = new Scanner(System.in);
System.out.print("Enter the number of quarters: ");
int quarters = inputScanner.nextInt();
System.out.print("Enter the number of dimes: ");
int dimes = inputScanner.nextInt();
System.out.print("Enter the number of nickles: ");
int nickles = inputScanner.nextInt();
System.out.print("Enter the number of pennies: ");
int pennies = inputScanner.nextInt();
inputScanner.close();
double total =0.00;
total = quarters * 0.25 + dimes * 0.1 + nickles * 0.05 + pennies * 0.01;
System.out.println("Total $" + total);
System.out.print("Thank you");
}
}
Your problem is related to how floating point (put easily, float/double related calculations) take place. Floating point numbers are an approximate reperesentation (if you are interested in the theory behind, the standard is IEEE754). Here you are getting exactly that, an approximate representation.
Since you are handling money, which goes only to cents (you cannot have 0.0001$ in currency), I suggest representing values with int (or long, or any integer type) values as cents. Then, divide by 100 when showing the result.
You have experienced the inexactness of representing floating-point numbers as doubles. The number 0.1 cannot be represented exactly in binary, so when you say 0.1 in Java, you get the closest possible approximation to 0.1. The same thing applies to 0.05 and 0.01.
There are a couple of things you can do:
Postpone floating-point arithmetic for as long as possible.
Example:
total = quarters * 25 + dimes * 10 + nickles * 5 + pennies;
total /= 100.0;
Use a DecimalFormat to cut off the display after two decimals.
Example:
DecimalFormat df = new DecimalFormat("0.00");
System.out.println("Total $" + df.format(total));
Neither of these workarounds gets around the basic issue - the inexact representation of a number by a double. Especially for amounts of money, don't use double. You could even use a BigDecimal instead, whose precision is arbitrary.
I agree with the explanations of why you are encountering this problem. My recommended solution for this sort of situation in Java is to use BigDecimal. It does exactly those calculations you would expect to be exact for short decimal fractions. For inexact calculations, it offers a good choice of rounding methods.
In effect, it does integer arithmetic with a scale factor, but automates storage and management of the scale.
Related
public class Rest {
public static void main(String[] args) {
double mealCost;
int tipPercent;
int taxPercent;
double totalCost;
Scanner scan = new Scanner(System.in);
mealCost = scan.nextDouble();
tipPercent = scan.nextInt();
taxPercent = scan.nextInt();
double tipInD = mealCost * (double)tipPercent / 100;
double taxInD = mealCost * (double)taxPercent / 100;
totalCost = (double)mealCost + (double)tipInD + (double)taxInD;
System.out.println("The total meal cost is "+(int)totalCost+" dollars.");
}
}
This is the program i have created and I have to pass 4 different input cases, 3 of which am passing with this code, but the fourth 1 am not able to.
input cases with expected o/p.
Input for 1st - 3rd cases
---------
12.00 20 8
----------
15.50 15 10
----------
20.75 10 3
Output for 1st - 3rd cases
---------
The total meal cost is 15 dollars.
---------
The total meal cost is 19 dollars.
---------
The total meal cost is 23 dollars.
For the 4th case, the code I have written is not able to give the wanted O/P for it.
Input
--------
10.25
17
5
Output Should Be
The total meal cost is 13 dollars.
And am Getting The total meal cost is 12 dollars.
Narrowing Primitive Conversion :
double to byte, short, char, int, long, or float
if the floating-point number is not an infinity, the floating-point value is rounded to an integer value V, rounding toward zero using IEEE 754 round-toward-zero mode (§4.2.3). Then there are two cases:
If T is long, and this integer value can be represented as a long, then the result of the first step is the long value V.
Otherwise, if this integer value can be represented as an int, then the result of the first step is the int value V.
(int)totalCost => (int) 12.504999999999999 => 12 (decimal part stripped)
Instead you may want to use Math.round( totalCost ) to get the closest integral value.
Math.round( totalCost ) => Math.round( 12.504999999999999 ) => 13
I think, from what you do expect, you just want to print:
System.out.println("The total meal cost is " + Math.round(totalCost) + " dollars.");
instead of.
System.out.println("The total meal cost is " +(int)totalCost + " dollars.");
The first one will properly round based on the mathematical rules, the second one will just stripe of the floating point values. That´s why the last one results in 12 and not 13, because it doesn´t actually round.
Change the way you write the totalCost to:
System.out.println("The total meal cost is "+ Math.round(totalCost) +" dollars.");
This will actually round off your output as per it should be calculated rather than just strip the decimal value directly.
A working solution is changing your output to
System.out.println("The total meal cost is " + (int) Math.ceil(totalCost) + " dollars.");
Explanation can be found here
You are casting an double value to an integer value. Note that by doing so you cut of the number at the decimal point and there is no rounding involved. Your calculation is 10.25*0.17 + 10.25*0.05 + 10.25 = 12.505
By applying the cast you get 12 and not 13. Don't cast your value, and you will be fine.
(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.
I'm trying to deal with money (probably the wrong way as far as best practices but I thought it would work.. its simple, multiply everything by 100 and then use ints)
import java.util.Scanner;
public class PFiveFifteen {
public static void main(String[] args)
{
Scanner in =new Scanner(System.in);
int i = 0;
double principalIn;
int duration=0;
double interestRate=0;
int thisYear = 0;
int iInterestRate = 0;
int iPrincipalIn = 0;
System.out.println("Please input initial amount: ");
principalIn = in.nextDouble();
iPrincipalIn= (int) principalIn *100;
//System.out.println(principalIn*100);
System.out.println("Please input interest rate as a decimal: ");
interestRate = in.nextDouble()*100;
iInterestRate = (int) interestRate;
//System.out.println(interestRate*100);
System.out.println("Please input duration of investment in years: ");
duration = in.nextInt();
//System.out.println(duration);
while(duration > i ) {
if ( i == 0) {
//System.out.println("Preloop value" + (iInterestRate));
thisYear = (iPrincipalIn * iInterestRate)+ iPrincipalIn;
//System.out.println("Postloop value" + (iPrincipalIn));
i++;
System.out.println("The initial value is " + thisYear);
System.out.println("Year # one one: " +i);
}
else
thisYear = (thisYear*iInterestRate) + thisYear;
i++;
System.out.println(thisYear/10000);
System.out.println("year # " +i);
}
But I'm somehow getting negative numbers back in console
Please input initial amount:
10000
Please input interest rate as a decimal:
100.00
Please input duration of investment in years:
10
The initial value is 1411065408
Year # one one: 1
141106
year # 2
-119738
year # 3
-72104
year # 4
4904
year # 5
84261
year # 6
21917
year # 7
154073
year # 8
-145664
year # 9
63722
year # 10
What in the world is going on here? I could get if there where whacky decimals or soemthing ( even though I cast it all to ints) but what the dickens is taking all positive inputs to below zero??
Your idea of representing money amounts as integers is an OK one, but you have to be very careful of the scaling, especially when you multiply (or divide). Say you start with a principal of $10, which you represent as 1000. Then you enter an interest rate of 0.06 (I assume that the user is entering an actual rate and not a percentage, so 0.06 means 6%). You then represent that as 6.
So if your principal is P, the int you're using to represent it is P*100. And if your interest rate is I, the int you're using to represent it is I*100.
So now you want to compute P*I. Since you're representing everything as 100 times the actual value, you presumably want to get an int whose value is P*I*100. But when you multiply the two ints you have, P*100 and I*100, the result is P*I*10000 -- a factor of 100 too high. That's because you multiplied the scale factors together along with the values. I can see that you did output thisYear / 10000, but you didn't change thisYear. So as you keep going through the loop, you will get values that are a factor of 10000 too high, and 1000000 too high, and so on, and eventually you will overflow. (I wish things really did work that way, but unfortunately I can't talk my bank into using your algorithm.)
To adjust, you'll need to divide this result by 100. (I'd add 50 to it first, so that when you divide by 100 the result will be rounded.)
looks like using ints was just ill conceived.
I did get it to play right with smaller numbers (the biggest issue was having to again bump up the principal by 100 to keep the correct place holder for when the interest which was (p*100)*(i*100) otherwise it was something *100 being added to the interest which was *10000. Sadly any realistic amount of money (like say 250000 for a house) overflows it before the first loop. Though 200000 makes it all the way to loop 30.
Plus interest rates aren't always hundredths, sometimes they are something like .03875
My code lacks the ability to determine the length and even if it had it bumping that up to an int, and keeping everything else like it (multiplying everything by 100000) would definitely not work.
Props to community for not calling me an idiot though! on Youtube et al, I would have gotten answers that would have put me into a corner crying!
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
//varible int time won't display the numeric value entered
The Speed of Sound
The following table shows the approximate speed of sound in air, water, and steel:
Medium Speed
Air 1,100 feet per second
Water 4,900 feet per second
Steel 16,400 feet per second
Write a program that asks the user to enter “air”, “water”, or “steel”, and the distance that
a sound wave will travel in the medium. The program should then display the amount of
time it will take. You can calculate the amount of time it takes sound to travel in air with
the following formula:
Time 5 Distance / 1,100
You can calculate the amount of time it takes sound to travel in water with the following formula:
Time 5 Distance / 4,900
You can calculate the amount of time it takes sound to travel in steel with the following formula:
Time 5 Distance / 16,400
C:\Users\DeLaCruz\Desktop\j2
V:\CSC106-Spring 2016\j3
import java.util.Scanner;
public class ProgramSpeedOfSound{
public static void main(String [] args){
Scanner keyboard = new Scanner(System.in);
String input;
System.out.println("Enter Air, water or steel ");
input = keyboard.nextLine().toUpperCase();
if(input.equals("Air")){
System.out.println("what is the Distance? ");
int Distance = keyboard.nextInt();
int var = 1100;
double time = Distance / var;
System.out.println("it would take " + time);
}
else if(input.equals("Water")){
System.out.println("what is the Distance? ");
int Distance = keyboard.nextInt();
double time = (((Distance/ 4900)));
System.out.println("it would take " + time);
}
else{
System.out.println("what is the Distance? ");
int Distance = keyboard.nextInt();
double time = Distance/ 16400;
System.out.println("it would take " + time);
}
}
}
You need to typecast either a denominator or numerator to float when dividing two integers. The reason you're getting 0.0 as answer is because division of two integers gives integer value as 0 which is later converted to double 0.0. For example see line 3 in the code below. You can also typecast to double.
System.out.println("what is the Distance? ");
int Distance = keyboard.nextInt();
double time = (float)Distance / 16400;
System.out.println("it would take " + time);
Below is the output after typecasting Distance to float
Enter Air, water or steel
Air
what is the Distance?
100
it would take 0.006097560748457909
Try using equalsIgnoreCase() instead of equals().
In your program, the control would not enter any of the conditional blocks if the value of input is not entered in the format you are checking.
Your code will not work for:
WATER, AIR, water etc.
So use equalsIgnoreCase() to avoid case sentivity.
Note:
Make the following correction:
Double Distance=keyboard.nextDouble();
Division of the type integer/integer may lead to loss in precision when the dividend is not completely divisible by the divisor.
5/3 will return 1 and you will lose the decimal part.
3/5 will return 0.
So it's better to declare Distance as Double instead of int.
Hi I'm having an issue while creating a change calculator for a school assignment. It essentially is to calculate the lowest amount of change needed for a certain amount of money.
Ex. $5.36:
2 toonies (2$)
1 loonie (1$)
1 quarter
1 dime
0 nickels
1 penny
I've stated all of my variable to be doubles so I can calculate the values and the totals together. It seems to work fine on whole numbers (5.00, 6.00, 7.00) but messes up whenever I add a decimal place. Like when I say $5.25 it should say 2 toonies 1 loonie and 1 quarter. I think it could be an error in rounding or something wrong with my calculations. Any Help is appreciated. Here is the calculations of the code:
//Rounding to one number
DecimalFormat oneDigit = new DecimalFormat ("#,0");
//Ask user for input
String moneyinput = JOptionPane.showInputDialog ("Welcome to the Change Caluculator. "
+ "Please Enter your amount of money in Dollars ($): ");
//Take user input and create into string.
totmoney = Double.parseDouble (moneyinput);
//Calculate number of toonies
numtoonies = (totmoney/toonieval);
System.out.println ("There is a total of " + oneDigit.format (numtoonies) + " toonies.");
//Find new amount
totmoney = (totmoney%toonieval);
//Calculate the number of loonies
numloonies = (totmoney/loonieval);
//Find new amount
totmoney = (totmoney-numloonies);
System.out.println ("There is a total of " + oneDigit.format (numloonies) + " loonies.");
//Calculate number of quarters
numquarters = (totmoney/quarterval);
//State the about of Coins
System.out.println ("There is a total of " + oneDigit.format (numquarters) + " quarters.");
}
I don't quite understand why you are using the DecimalFormat at all. You should be able to do solve this with only mod % and division /.
This is how I would approach this problem:
Take the input from the user (as a double in the format 5.33)
Save that as int by moving the decimal place (int value = cost * 100)
Find the number of toonies by using division (numToonies = value / toonieval)
Find the remaining amount of money by (value = value % toonieval)
Repeat steps 3 and 4 for the other denominations
Note: you will have to modify the values of the toonies to reflect the fact that the price you used was multiplied by 100.
I don't think this is working properly for floating point numbers:
totmoney = (totmoney%toonieval);
Try
totmoney = totmoney - toonieval*numtoonies;
instead.
Also, be aware that floating point values are generally not suitable for handling monetary values (because of the possiblity of rounding errors). Use fixed point decimals instead (basically, store the value in cents and calculate everyting on a cents base).
Do not use floating point numbers when you need absolute accuracy. The IEEE floating point specification which java follows even states that there will be a loss of precision because the floating point spec can not properly represent all floating point operations it can only approximate them. The solution for this is that you need to store the value in 2 ints, one for the amount left of the decimal and one for the value to the right of the decimal