I am writing a program that will simulate a cash register change calculator. It should print the change and how to give back the change ( number of twenty, tens, fives, quarters, dimes, etc).
The problem is that when I compile the program, I get a big number. I've tried rounding it down but it doesn't work. ALSO, I don't know if it is caused by the change not being rounded but I won't get the number of cents, I only get 1 $10 bill.
p.s. I am taking a high school CS course and right now I can't use other methods of rounding it, I know there is a way like the one I attempted below (casting and stuff) which I am allowed to use at the moment.
Thank you.
public class changeCash
{
public static void main(String[] args)
{
double cost = 68.90;
double amtPaid = 80.00;
double change = 0;
int twentyBill= 0;
int tenBill = 0;
int fiveBill = 0;
int oneBill = 0;
int quarters = 0;
int dimes = 0;
int nickels = 0;
int pennies = 0;
change = amtPaid - cost;
change = ((int)change * 10) / 10.0;
System.out.println("Your change is " +"$" + change);
double back = amtPaid - cost;
if(back >= 20)
{
twentyBill++;
back -= 20;
System.out.println(twentyBill + " $20 bill(s)");
}
else if(back >= 10)
{
tenBill++;
back -= 10;
System.out.println(tenBill + " $10 bill(s)");
}
else if(back >= 5)
{
fiveBill++;
back -= 5;
System.out.println(fiveBill + " $5 bills(s)");
}
else if(back >= 1)
{
oneBill++;
back -= 1;
System.out.println(oneBill + " $1 bills(s)");
}
else if(back >= 0.25)
{
quarters++;
back -= 0.25;
System.out.println(quarters + " qaurter(s)");
}
else if(back >= 0.10)
{
dimes++;
back -= 0.10;
System.out.println(dimes + " dime(s)");
}
else if(back >= 0.05)
{
nickels++;
back -= 0.05;
System.out.println(nickels + " nickel(s)");
}
else if(back >= 0.01)
{
pennies++;
back -= 0.01;
System.out.println(pennies + " penny(ies)");
}
}
}
Couple of issues. First, smaller one:
change = amtPaid - cost;
Change is 11.1, as it should be, but then:
change = ((int)change * 10) / 10.0;
Casts take precedence over arithmetic, so first (int)change happens (which results in 11), then it is multiplied by 10, then divided by 10.0, and you end up with 11.0 instead of 11.1.
But your bigger problem is in your if statements. You have a series of if...else. Once one of these executes, the remainder of the else blocks will not. So when you have e.g.:
if (back >= 20) {
...
} else if (back >= 10) {
...
} else if (back >= 5) {
...
} else ...
As soon as one hits, it's done. If back >= 20 is false it goes to the next. Then if back >= 10 is true, it executes that, then doesn't execute the rest, so you would want to separate them, e.g.:
if (back >= 20) {
...
}
if (back >= 10) {
...
}
if (back >= 5) {
...
}
...
That'll get you closer, but you're still not quite there. For example, what if your change is 40? That will be two 20's. But your if statement will only take away a single 20. To that end, a while loop would be appropriate. It also more accurately reflects reality. In real life if you had to give somebody $40, you wouldn't just give them a single $20 and walk away, you'd get a dirty look. You'd keep giving them $20's until the amount you owed them was less than $20. So for example:
while (back >= 20) {
...
}
while (back >= 10) {
...
}
while (back >= 5) {
...
}
...
You want your code to reflect the logic you would use in reality.
Regarding your question in comments:
... why do I get $11.099999999999994 instead of just 11.1?
Floating-point rounding error. Decimal numbers are not 100% accurate; "11.1" can't be represented precisely. You have a couple of ways to work around it. You could round to two decimals when you display the number, e.g. System.out.printf("%.2f", change). However, you may want to use int and store the number of cents, rather than using double and storing the number of dollars. Working with integers is more precise, and actually, when working with currency in important applications, integers are often used for this reason.
Simpler Solution
double d = 2.99999999;
long l = (long) d;
Math.class, floor function
double d = Math.floor(2.55555) //result: 2.0
Returns the largest (closest to positive infinity) double value that
is less than or equal to the argument and is equal to a mathematical
integer
Find below the code which works well. Tested with different values. We want to avoid more than 2 decimal places hence I have added several utility methods just to do that.
Uncomment different cost values to see its working in different scenarios.
public class ChangeCash {
public static void main(String[] args) {
double cost = 65.90;
// cost = 68.33;
// cost = 42.27;
double amtPaid = 80.00;
double change = 0;
int twentyBill = 0;
int tenBill = 0;
int fiveBill = 0;
int oneBill = 0;
int quarters = 0;
int dimes = 0;
int nickels = 0;
int pennies = 0;
change = amtPaid - cost;
System.out.format("Your change is $ %.2f", decimalCeil(change, true));
System.out.println();
double back = decimalCeil(change, true);
if (back >= 20) {
twentyBill++;
back -= 20;
System.out.println(twentyBill + " $20 bill(s)");
}
if (back >= 10) {
tenBill++;
back -= 10;
System.out.println(tenBill + " $10 bill(s)");
}
if (back >= 5) {
fiveBill++;
back -= 5;
System.out.println(fiveBill + " $5 bills(s)");
}
if (back >= 1) {
oneBill = (int) (back * 10) / 10;
back -= oneBill;
System.out.println(oneBill + " $1 bills(s)");
}
if (decimalCeil(back) >= 0.25) {
quarters = (int) (back * 100) / 25;
back = correct2DecimalPlaces(back, 25);
System.out.println(quarters + " qaurter(s)");
}
back = (int) (decimalCeil(back, true) * 100);
if (back >= 10) {
dimes = (int) (back / 10);
back = back % 10;
System.out.println(dimes + " dime(s)");
}
if (back >= 5) {
nickels = (int) (back / 5);
back = back % 5;
System.out.println(nickels + " nickel(s)");
}
if (back >= 1) {
pennies = (int) back;
System.out.println(pennies + " penny(s)");
}
}
private static double correct2DecimalPlaces(double back, int modulo) {
int correctTwoPlaces = (int) (back * 100) % modulo;
back = (double) correctTwoPlaces / 100;
return back;
}
private static double decimalCeil(double change) {
int temp = (int) (change * 100);
double tempWithCeil = Math.ceil(temp);
double answer = tempWithCeil / 100;
return answer;
}
private static double decimalCeil(double change, boolean decimalThreePlaces) {
double temp = change * 1000;
double tempWithCeil = Math.ceil(temp);
double answer = tempWithCeil / 1000;
return answer;
}
}
Related
This question already has answers here:
Division of integers in Java [duplicate]
(7 answers)
Closed 6 years ago.
I'm currently doing an assignment for school, and I need to create a program that uses Math.random() to get a random value, and depending on the value, output "Heads" or "Tails". It needs to do this 10 times. Then, it needs to find the percentage of times that the program output heads, and how many it output tails. However, it isn't working correctly. It always outputs that heads/tails were 0% of the tosses. Can someone please explain why?
public class HeadsTails
{
public static void main(String[] args)
{
int v;
double i;
int heads = 0, tails = 0;
double headsPercent, tailsPercent;
for(v = 1; v <= 10; ++v)
{
i = Math.random();
if(i <= 0.5)
{
System.out.println("Heads");
heads = heads + 1;
}
else if(i > 0.5)
{
System.out.println("Tails");
tails = tails + 1;
}
}
headsPercent = (heads / 10) * 100;
tailsPercent = (tails / 10) * 100;
System.out.println("Heads were " + headsPercent + "% of the tosses.");
System.out.println("Tails were " + tailsPercent + "% of the tosses.");
}
}
I am also quite open to any improvements that can be made, besides those that just make the program function properly.
The problem is integer math. heads and tails are both int, so:
heads / 10
...yields an int result, which will almost always be 0 in your case because in int-land, 1 / 10, 2 / 10, through 9 / 10 are all 0. The only time you'd get anything else would be if all the rolls were heads or all were tails, where 10 / 10 is 1.
Cast to double before doing the math:
headsPercent = ((double)heads / 10) * 100;
tailsPercent = ((double)tails / 10) * 100;
Doing that fixes the problem.
Side note 1: You can add to a variable using +=, e.g.:
heads += x;
And of course, when what you're adding is 1, you can just use the increment operators, either prefix:
++heads;
or postfix
heads++;
(In terms of updating heads and tails, it doesn't matter which.)
Side note 2: You don't need else if (i > 0.5). If you think about the logic, you have if (i <= 0.5) ... else ... That means that i will definitely be > 0.5 once you get to the else, no need for the if (i > 0.5) part.
And if you do that, you don't even need i anymore:
for(v = 1; v <= 10; ++v)
{
if(Math.random() <= 0.5)
{
System.out.println("Heads");
++heads;
}
else
{
System.out.println("Tails");
++tails;
}
}
Note: Updated on 06/17/2015. Of course this is possible. See the solution below.
Even if anyone copies and pastes this code, you still have a lot of cleanup to do. Also note that you will have problems inside the critical strip from Re(s) = 0 to Re(s) = 1 :). But this is a good start.
import java.util.Scanner;
public class NewTest{
public static void main(String[] args) {
RiemannZetaMain func = new RiemannZetaMain();
double s = 0;
double start, stop, totalTime;
Scanner scan = new Scanner(System.in);
System.out.print("Enter the value of s inside the Riemann Zeta Function: ");
try {
s = scan.nextDouble();
}
catch (Exception e) {
System.out.println("You must enter a positive integer greater than 1.");
}
start = System.currentTimeMillis();
if (s <= 0)
System.out.println("Value for the Zeta Function = " + riemannFuncForm(s));
else if (s == 1)
System.out.println("The zeta funxtion is undefined for Re(s) = 1.");
else if(s >= 2)
System.out.println("Value for the Zeta Function = " + getStandardSum(s));
else
System.out.println("Value for the Zeta Function = " + getNewSum(s));
stop = System.currentTimeMillis();
totalTime = (double) (stop-start) / 1000.0;
System.out.println("Total time taken is " + totalTime + " seconds.");
}
// Standard form the the Zeta function.
public static double standardZeta(double s) {
int n = 1;
double currentSum = 0;
double relativeError = 1;
double error = 0.000001;
double remainder;
while (relativeError > error) {
currentSum = Math.pow(n, -s) + currentSum;
remainder = 1 / ((s-1)* Math.pow(n, (s-1)));
relativeError = remainder / currentSum;
n++;
}
System.out.println("The number of terms summed was " + n + ".");
return currentSum;
}
public static double getStandardSum(double s){
return standardZeta(s);
}
//New Form
// zeta(s) = 2^(-1+2 s)/((-2+2^s) Gamma(1+s)) integral_0^infinity t^s sech^2(t) dt for Re(s)>-1
public static double Integrate(double start, double end) {
double currentIntegralValue = 0;
double dx = 0.0001d; // The size of delta x in the approximation
double x = start; // A = starting point of integration, B = ending point of integration.
// Ending conditions for the while loop
// Condition #1: The value of b - x(i) is less than delta(x).
// This would throw an out of bounds exception.
// Condition #2: The value of b - x(i) is greater than 0 (Since you start at A and split the integral
// up into "infinitesimally small" chunks up until you reach delta(x)*n.
while (Math.abs(end - x) >= dx && (end - x) > 0) {
currentIntegralValue += function(x) * dx; // Use the (Riemann) rectangle sums at xi to compute width * height
x += dx; // Add these sums together
}
return currentIntegralValue;
}
private static double function(double s) {
double sech = 1 / Math.cosh(s); // Hyperbolic cosecant
double squared = Math.pow(sech, 2);
return ((Math.pow(s, 0.5)) * squared);
}
public static double getNewSum(double s){
double constant = Math.pow(2, (2*s)-1) / (((Math.pow(2, s)) -2)*(gamma(1+s)));
return constant*Integrate(0, 1000);
}
// Gamma Function - Lanczos approximation
public static double gamma(double s){
double[] p = {0.99999999999980993, 676.5203681218851, -1259.1392167224028,
771.32342877765313, -176.61502916214059, 12.507343278686905,
-0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7};
int g = 7;
if(s < 0.5) return Math.PI / (Math.sin(Math.PI * s)*gamma(1-s));
s -= 1;
double a = p[0];
double t = s+g+0.5;
for(int i = 1; i < p.length; i++){
a += p[i]/(s+i);
}
return Math.sqrt(2*Math.PI)*Math.pow(t, s+0.5)*Math.exp(-t)*a;
}
//Binomial Co-efficient - NOT CURRENTLY USING
/*
public static double binomial(int n, int k)
{
if (k>n-k)
k=n-k;
long b=1;
for (int i=1, m=n; i<=k; i++, m--)
b=b*m/i;
return b;
} */
// Riemann's Functional Equation
// Tried this initially and utterly failed.
public static double riemannFuncForm(double s) {
double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s);
double nextTerm = Math.pow(2, (1-s))*Math.pow(Math.PI, (1-s)-1)*(Math.sin((Math.PI*(1-s))/2))*gamma(1-(1-s));
double error = Math.abs(term - nextTerm);
if(s == 1.0)
return 0;
else
return Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s)*standardZeta(1-s);
}
}
Ok well we've figured out that for this particular function, since this form of it isn't actually a infinite series, we cannot approximate using recursion. However the infinite sum of the Riemann Zeta series (1\(n^s) where n = 1 to infinity) could be solved through this method.
Additionally this method could be used to find any infinite series' sum, product, or limit.
If you execute the code your currently have, you'll get infinite recursion as 1-(1-s) = s (e.g. 1-s = t, 1-t = s so you'll just switch back and forth between two values of s infinitely).
Below I talk about the sum of series. It appears you are calculating the product of the series instead. The concepts below should work for either.
Besides this, the Riemann Zeta Function is an infinite series. This means that it only has a limit, and will never reach a true sum (in finite time) and so you cannot get an exact answer through recursion.
However, if you introduce a "threshold" factor, you can get an approximation that is as good as you like. The sum will increase/decrease as each term is added. Once the sum stabilizes, you can quit out of recursion and return your approximate sum. "Stabilized" is defined using your threshold factor. Once the sum varies by an amount less than this threshold factor (which you have defined), your sum has stabilized.
A smaller threshold leads to a better approximation, but also longer computation time.
(Note: this method only works if your series converges, if it has a chance of not converging, you might also want to build in a maxSteps variable to cease execution if the series hasn't converged to your satisfaction after maxSteps steps of recursion.)
Here's an example implementation, note that you'll have to play with threshold and maxSteps to determine appropriate values:
/* Riemann's Functional Equation
* threshold - if two terms differ by less than this absolute amount, return
* currSteps/maxSteps - if currSteps becomes maxSteps, give up on convergence and return
* currVal - the current product, used to determine threshold case (start at 1)
*/
public static double riemannFuncForm(double s, double threshold, int currSteps, int maxSteps, double currVal) {
double nextVal = currVal*(Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s)); //currVal*term
if( s == 1.0)
return 0;
else if ( s == 0.0)
return -0.5;
else if (Math.abs(currVal-nextVal) < threshold) //When a term will change the current answer by less than threshold
return nextVal; //Could also do currVal here (shouldn't matter much as they differ by < threshold)
else if (currSteps == maxSteps)//When you've taken the max allowed steps
return nextVal; //You might want to print something here so you know you didn't converge
else //Otherwise just keep recursing
return riemannFuncForm(1-s, threshold, ++currSteps, maxSteps, nextVal);
}
}
This is not possible.
The functional form of the Riemann Zeta Function is --
zeta(s) = 2^s pi^(-1+s) Gamma(1-s) sin((pi s)/2) zeta(1-s)
This is different from the standard equation in which an infinite sum is measured from 1/k^s for all k = 1 to k = infinity. It is possible to write this as something similar to --
// Standard form the the Zeta function.
public static double standardZeta(double s) {
int n = 1;
double currentSum = 0;
double relativeError = 1;
double error = 0.000001;
double remainder;
while (relativeError > error) {
currentSum = Math.pow(n, -s) + currentSum;
remainder = 1 / ((s-1)* Math.pow(n, (s-1)));
relativeError = remainder / currentSum;
n++;
}
System.out.println("The number of terms summed was " + n + ".");
return currentSum;
}
The same logic doesn't apply to the functional equation (it isn't a direct sum, it is a mathematical relationship). This would require a rather clever way of designing a program to calculate negative values of Zeta(s)!
The literal interpretation of this Java code is ---
// Riemann's Functional Equation
public static double riemannFuncForm(double s) {
double currentVal = (Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s));
if( s == 1.0)
return 0;
else if ( s == 0.0)
return -0.5;
else
System.out.println("Value of next value is " + nextVal(1-s));
return currentVal;//*nextVal(1-s);
}
public static double nextVal(double s)
{
return (Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s));
}
public static double getRiemannSum(double s) {
return riemannFuncForm(s);
}
Testing on three or four values shows that this doesn't work. If you write something similar to --
// Riemann's Functional Equation
public static double riemannFuncForm(double s) {
double currentVal = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s); //currVal*term
if( s == 1.0)
return 0;
else if ( s == 0.0)
return -0.5;
else //Otherwise just keep recursing
return currentVal * nextVal(1-s);
}
public static double nextVal(double s)
{
return (Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s));
}
I was misinterpretation how to do this through mathematics. I will have to use a different approximation of the zeta function for values less than 2.
I think I need to use a different form of the zeta function. When I run the entire program ---
import java.util.Scanner;
public class Test4{
public static void main(String[] args) {
RiemannZetaMain func = new RiemannZetaMain();
double s = 0;
double start, stop, totalTime;
Scanner scan = new Scanner(System.in);
System.out.print("Enter the value of s inside the Riemann Zeta Function: ");
try {
s = scan.nextDouble();
}
catch (Exception e) {
System.out.println("You must enter a positive integer greater than 1.");
}
start = System.currentTimeMillis();
if(s >= 2)
System.out.println("Value for the Zeta Function = " + getStandardSum(s));
else
System.out.println("Value for the Zeta Function = " + getRiemannSum(s));
stop = System.currentTimeMillis();
totalTime = (double) (stop-start) / 1000.0;
System.out.println("Total time taken is " + totalTime + " seconds.");
}
// Standard form the the Zeta function.
public static double standardZeta(double s) {
int n = 1;
double currentSum = 0;
double relativeError = 1;
double error = 0.000001;
double remainder;
while (relativeError > error) {
currentSum = Math.pow(n, -s) + currentSum;
remainder = 1 / ((s-1)* Math.pow(n, (s-1)));
relativeError = remainder / currentSum;
n++;
}
System.out.println("The number of terms summed was " + n + ".");
return currentSum;
}
public static double getStandardSum(double s){
return standardZeta(s);
}
// Riemann's Functional Equation
public static double riemannFuncForm(double s, double threshold, double currSteps, int maxSteps) {
double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s);
//double nextTerm = Math.pow(2, (1-s))*Math.pow(Math.PI, (1-s)-1)*(Math.sin((Math.PI*(1-s))/2))*gamma(1-(1-s));
//double error = Math.abs(term - nextTerm);
if(s == 1.0)
return 0;
else if (s == 0.0)
return -0.5;
else if (term < threshold) {//The recursion will stop once the term is less than the threshold
System.out.println("The number of steps is " + currSteps);
return term;
}
else if (currSteps == maxSteps) {//The recursion will stop if you meet the max steps
System.out.println("The series did not converge.");
return term;
}
else //Otherwise just keep recursing
return term*riemannFuncForm(1-s, threshold, ++currSteps, maxSteps);
}
public static double getRiemannSum(double s) {
double threshold = 0.00001;
double currSteps = 1;
int maxSteps = 1000;
return riemannFuncForm(s, threshold, currSteps, maxSteps);
}
// Gamma Function - Lanczos approximation
public static double gamma(double s){
double[] p = {0.99999999999980993, 676.5203681218851, -1259.1392167224028,
771.32342877765313, -176.61502916214059, 12.507343278686905,
-0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7};
int g = 7;
if(s < 0.5) return Math.PI / (Math.sin(Math.PI * s)*gamma(1-s));
s -= 1;
double a = p[0];
double t = s+g+0.5;
for(int i = 1; i < p.length; i++){
a += p[i]/(s+i);
}
return Math.sqrt(2*Math.PI)*Math.pow(t, s+0.5)*Math.exp(-t)*a;
}
//Binomial Co-efficient
public static double binomial(int n, int k)
{
if (k>n-k)
k=n-k;
long b=1;
for (int i=1, m=n; i<=k; i++, m--)
b=b*m/i;
return b;
}
}
I notice that plugging in zeta(-1) returns -
Enter the value of s inside the Riemann Zeta Function: -1
The number of steps is 1.0
Value for the Zeta Function = -0.0506605918211689
Total time taken is 0.0 seconds.
I knew that this value was -1/12. I checked some other values with wolfram alpha and observed that --
double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s);
Returns the correct value. It is just that I am multiplying this value every time by zeta(1-s). In the case of Zeta(1/2), this will always multiply the result by 0.99999999.
Enter the value of s inside the Riemann Zeta Function: 0.5
The series did not converge.
Value for the Zeta Function = 0.999999999999889
Total time taken is 0.006 seconds.
I am going to see if I can replace the part for --
else if (term < threshold) {//The recursion will stop once the term is less than the threshold
System.out.println("The number of steps is " + currSteps);
return term;
}
This difference is the error between two terms in the summation. I may not be thinking about this correctly, it is 1:16am right now. Let me see if I can think better tomorrow ....
I am developing a simple Taxi Meter Calculator system. I have no idea what to use to implement it. I have written a code but got stuck at IF statement where I had to insert an array variable. I am not sure whether this is the correct way to implement it.
This is the logic.
The first Km is 50/-.
Then the next 10Km will be charged 45/- per Km. eg : if 2km were gone
, charges would be 50/- + 45/- = 95/-, if 3km were gone 140/-.
The next 10km will be charged 35/- per km
25/- per km will be charged no matter how many kms gone after the above 10km exceed.
This is the code I have coded so far
private void btn_calActionPerformed(java.awt.event.ActionEvent evt) {
int kms1 = 50;
int kms2 = 45;
int kms3 = 35;
int kms4 = 25;
String[] firstkm={"3,4,5,6,7,8,9,10,11"};
if(txt_km.getText().equals("1")){
lblout.setText(""+kms1);
}
if(txt_km.getText().equals("2")){
lblout.setText(""+(kms1+kms2));
}if(txt_km.getText().equals(firstkm)){
int get = Integer.parseInt(txt_km.getText());
int rate = get+kms2;
lblout.setText(""+rate);
}
}
if there is any other method to solve this problem please mention it.
int fare = 0;
int distance = 0;
if (distance > 21) {
fare += (distance - 21) * 25;
distance = 21;
}
if (distance > 11) {
fare += (distance - 11) * 35;
distance = 11;
}
if (distance > 1) {
fare += (distance - 1) * 45;
distance = 1;
}
if (distance > 0) {
fare += distance * 50;
}
Then refactor by putting the magic numbers into arrays and loop through the arrays (4 times).
Here's a hint: Implement this method
/**
This method returns the amount a passenger must pay for this kilometer of their trip
*/
public int chargeForKilometer(int kilometerNumberInTrip) {
//...
}
try
String[] firstkm={3,4,5,6,7,8,9,10,11};
if(txt_km.getText().equals(firstkm[1])){
lblout.setText(""+kms1);
}
....
In case your conditions change and you want to avoid adding if conditions in your code, I wrote a configurable code.
public int calculateRate(int kmCount){
int baseRate = 50;
int[] stepRate = {45,35};
int step = 10;
int fare = 0;
int threshold = 21;
int beyondThresholdRate = 25;
if(kmCount>0){
fare = baseRate;
fare += (kmCount - threshold)<0?0:(kmCount - threshold)*beyondThresholdRate;
kmCount = kmCount - 1;
for(int i=0;i<=((kmCount/step) + (kmCount%step>0?1:0));i++){
fare += (kmCount/step)==0?(kmCount%step)*stepRate[i]:step*stepRate[i];
kmCount -=step;
if(i==stepRate.length-1) break;
}
}
return fare;
}
It is slightly complex, however, flexible.
This question already has answers here:
Java: Inaccuracy using double [duplicate]
(4 answers)
Closed 9 years ago.
I am getting strange output when I add doubles together. Can someone tell me why I'm getting repeating decimals when I am adding 0.1 every time?
I have worked out the formula for adding these numbers together and I have done this myself on paper up to 3.3... The sum of all numbers (decreasing by 1 tenth) from 3.3 to 1 equals 51.6
3.3
3.2
3.1 +
3.0
...
1.0
_
51.6
There is an easier way to calculate this using two formulas:
The linear formula for the increasing number: Y = 0.1X + 1
And the sum of increasing numbers formula: [X * (Y + 1)]/2 = total
first solve for Y using any number (in this case 100)
11 = 0.1(100) + 1
Then solve for the total using X and Y
[100 * (11+1)]/2 = 600
The output of the following code should be 600 I believe. There is no question that it should not have a repeating decimal. What am I doing wrong here? There must be something I missed.
public static void main(String[] args) {
int days = 100;
double inc = 0.1;
double init = 1;
double total = 0;
for (int i = 1; i <= days; i++) {
if (i == 1) {
total = total + init;
} else {
init = init + inc;
total = total + init;
}
}
System.out.println("Total: " + total);
System.out.println("Daily: " + init);
}
Double does not have infinite precision (Neither does BigDecimal, but BigDecimal has sufficient precision for this implementation).
Try this,
public static void main(String[] args) {
int days = 100;
java.math.BigDecimal init = java.math.BigDecimal.ONE;
java.math.BigDecimal total = java.math.BigDecimal.ZERO;
java.math.BigDecimal oneTenth = new java.math.BigDecimal(
"0.1");
for (int i = 1; i <= days; i++) {
if (i != 1) {
init = init.add(oneTenth);
}
total = total.add(init);
}
System.out.println("Total: " + total);
System.out.println("Daily: " + init);
}
Which outputs
Total: 595.0
Daily: 10.9
Please read the link that Don Roby posted. In essence, double precision is not a good way to represent fractions. A number like 0.1 does not have an exact representation in binary float notation - because floating point numbers are written as "something times two to the power something else". And you cannot solve that exactly for 0.1. Thus, you are really getting a slightly smaller number - actually
0.0999999999999998
And that missing amount is enough to mess up the math…
See Jon Skeet's very excellent answer on this topic: https://stackoverflow.com/a/1089026/1967396
The formula should be
0.1 * (100 * (100 + 1) / 2)
except you start at 10 * 0.1 so the formula is more complicated.
In any case double precision is not exact esp for numbers like 0.1, so you should expect to get rounding error.
You can work around this by using numbers which can be represented accurately like 1 instead of 0.1 (or rounding the result)
public static void main(String... ignored) {
int days = 100;
double inc = 1;
double init = 10;
double total = 0;
for (int i = 1; i <= days; i++) {
if (i == 1) {
total = total + init;
} else {
init = init + inc;
total = total + init;
}
}
total /= 10;
init /= 10;
System.out.println("Total: " + total);
System.out.println("Daily: " + init);
}
or round the result.
public static void main(String... ignored) {
int days = 100;
double inc = 0.1;
double init = 1;
double total = 0;
for (int i = 1; i <= days; i++) {
if (i == 1) {
total = total + init;
} else {
init = init + inc;
total = total + init;
}
}
System.out.printf("Total: %.1f%n", total);
System.out.printf("Daily: %.1f%n", init);
}
both print
Total: 595.0
Daily: 10.9
Does anyone know how to round up a number to its nearest multiple of 5? I found an algorithm to round it to the nearest multiple of 10 but I can't find this one.
This does it for ten.
double number = Math.round((len + 5)/ 10.0) * 10.0;
To round to the nearest of any value:
int round(double value, int nearest) {
return (int) Math.round(value / nearest) * nearest;
}
You can also replace Math.round() with either Math.floor() or Math.ceil() to make it always round down or always round up.
int roundUp(int n) {
return (n + 4) / 5 * 5;
}
Note - YankeeWhiskey's answer is rounding to the closest multiple, this is rounding up. Needs a modification if you need it to work for negative numbers. Note that integer division followed by integer multiplication of the same number is the way to round down.
I think I have it, thanks to Amir
double round( double num, int multipleOf) {
return Math.floor((num + multipleOf/2) / multipleOf) * multipleOf;
}
Here's the code I ran
class Round {
public static void main(String[] args){
System.out.println("3.5 round to 5: " + Round.round(3.5, 5));
System.out.println("12 round to 6: " + Round.round(12, 6));
System.out.println("11 round to 7: "+ Round.round(11, 7));
System.out.println("5 round to 2: " + Round.round(5, 2));
System.out.println("6.2 round to 2: " + Round.round(6.2, 2));
}
public static double round(double num, int multipleOf) {
return Math.floor((num + (double)multipleOf / 2) / multipleOf) * multipleOf;
}
}
And here's the output
3.5 round to 5: 5.0
12 round to 6: 12.0
11 round to 7: 14.0
5 round to 2: 6.0
6.2 round to 2: 6.0
int roundUp(int num) {
return (int) (Math.ceil(num / 5d) * 5);
}
int roundUp(int num) {
return ((num / 5) + (num % 5 > 0 ? 1 : 0)) * 5;
}
int round(int num) {
int temp = num%5;
if (temp<3)
return num-temp;
else
return num+5-temp;
}
int getNextMultiple(int num , int multipleOf) {
int nextDiff = multipleOf - (num % multipleOf);
int total = num + nextDiff;
return total;
}
int roundToNearestMultiple(int num, int multipleOf){
int floorNearest = ((int) Math.floor(num * 1.0/multipleOf)) * multipleOf;
int ceilNearest = ((int) Math.ceil(num * 1.0/multipleOf)) * multipleOf;
int floorNearestDiff = Math.abs(floorNearest - num);
int ceilNearestDiff = Math.abs(ceilNearest - num);
if(floorNearestDiff <= ceilNearestDiff) {
return floorNearest;
} else {
return ceilNearest;
}
}
This Kotlin function rounds a given value 'x' to the closest multiple of 'n'
fun roundXN(x: Long, n: Long): Long {
require(n > 0) { "n(${n}) is not greater than 0."}
return if (x >= 0)
((x + (n / 2.0)) / n).toLong() * n
else
((x - (n / 2.0)) / n).toLong() * n
}
fun main() {
println(roundXN(121,4))
}
Output: 120
Kotlin with extension function.
Possible run on play.kotlinlang.org
import kotlin.math.roundToLong
fun Float.roundTo(roundToNearest: Float): Float = (this / roundToNearest).roundToLong() * roundToNearest
fun main() {
println(1.02F.roundTo(1F)) // 1.0
println(1.9F.roundTo(1F)) // 2.0
println(1.5F.roundTo(1F)) // 2.0
println(1.02F.roundTo(0.5F)) // 1.0
println(1.19F.roundTo(0.5F)) // 1.0
println(1.6F.roundTo(0.5F)) // 1.5
println(1.02F.roundTo(0.1F)) // 1.0
println(1.19F.roundTo(0.1F)) // 1.2
println(1.51F.roundTo(0.1F)) // 1.5
}
Possible to use floor/ceil like this:
fun Float.floorTo(roundToNearest: Float): Float = floor(this / roundToNearest) * roundToNearest
Some people are saying something like
int n = [some number]
int rounded = (n + 5) / 5 * 5;
This will round, say, 5 to 10, as well as 6, 7, 8, and 9 (all to 10). You don't want 5 to round to 10 though. When dealing with just integers, you want to instead add 4 to n instead of 5. So take that code and replace the 5 with a 4:
int n = [some number]
int rounded = (n + 4) / 5 * 5;
Of course, when dealing with doubles, just put something like 4.99999, or if you want to account for all cases (if you might be dealing with even more precise doubles), add a condition statement:
int n = [some number]
int rounded = n % 5 == 0 ? n : (n + 4) / 5 * 5;
Another Method or logic to rounding up a number to nearest multiple of 5
double num = 18.0;
if (num % 5 == 0)
System.out.println("No need to roundoff");
else if (num % 5 < 2.5)
num = num - num % 5;
else
num = num + (5 - num % 5);
System.out.println("Rounding up to nearest 5------" + num);
output :
Rounding up to nearest 5------20.0
I've created a method that can convert a number to the nearest that will be passed in, maybe it will help to someone, because i saw a lot of ways here and it did not worked for me but this one did:
/**
* The method is rounding a number per the number and the nearest that will be passed in.
* If the nearest is 5 - (63->65) | 10 - (124->120).
* #param num - The number to round
* #param nearest - The nearest number to round to (If the nearest is 5 -> (0 - 2.49 will round down) || (2.5-4.99 will round up))
* #return Double - The rounded number
*/
private Double round (double num, int nearest) {
if (num % nearest >= nearest / 2) {
num = num + ((num % nearest - nearest) * -1);
} else if (num % nearest < nearest / 2) {
num = num - (num % nearest);
}
return num;
}
In case you only need to round whole numbers you can use this function:
public static long roundTo(long value, long roundTo) {
if (roundTo <= 0) {
throw new IllegalArgumentException("Parameter 'roundTo' must be larger than 0");
}
long remainder = value % roundTo;
if (Math.abs(remainder) < (roundTo / 2d)) {
return value - remainder;
} else {
if (value > 0) {
return value + (roundTo - Math.abs(remainder));
} else {
return value - (roundTo - Math.abs(remainder));
}
}
}
The advantage is that it uses integer arithmetics and works even for large long numbers where the floating point division will cause you problems.
int roundUp(int n, int multipleOf)
{
int a = (n / multipleOf) * multipleOf;
int b = a + multipleOf;
return (n - a > b - n)? b : a;
}
source: https://www.geeksforgeeks.org/round-the-given-number-to-nearest-multiple-of-10/
Praveen Kumars question elsewhere in this Thread
"Why are we adding 4 to the number?"
is very relevant. And it is why I prefer to code it like this:
int roundUpToMultipleOf5(final int n) {
return (n + 5 - 1) / 5 * 5;
}
or, passing the value as an argument:
int roundUpToMultiple(final int n, final int multipleOf) {
return (n + multipleOf - 1) / multipleOf * multipleOf;
}
By adding 1 less than the multiple you're looking for, you've added just enough to make sure that a value of n which is an exact multiple will not round up, and any value of n which is not an exact multiple will be rounded up to the next multiple.
Recursive:
public static int round(int n){
return (n%5==0) ? n : round(++n);
}
Just pass your number to this function as a double, it will return you rounding the decimal value up to the nearest value of 5;
if 4.25, Output 4.25
if 4.20, Output 4.20
if 4.24, Output 4.20
if 4.26, Output 4.30
if you want to round upto 2 decimal places,then use
DecimalFormat df = new DecimalFormat("#.##");
roundToMultipleOfFive(Double.valueOf(df.format(number)));
if up to 3 places, new DecimalFormat("#.###")
if up to n places, new DecimalFormat("#.nTimes #")
public double roundToMultipleOfFive(double x)
{
x=input.nextDouble();
String str=String.valueOf(x);
int pos=0;
for(int i=0;i<str.length();i++)
{
if(str.charAt(i)=='.')
{
pos=i;
break;
}
}
int after=Integer.parseInt(str.substring(pos+1,str.length()));
int Q=after/5;
int R =after%5;
if((Q%2)==0)
{
after=after-R;
}
else
{
after=after+(5-R);
}
return Double.parseDouble(str.substring(0,pos+1).concat(String.valueOf(after))));
}
Here's what I use for rounding to multiples of a number:
private int roundToMultipleOf(int current, int multipleOf, Direction direction){
if (current % multipleOf == 0){
return ((current / multipleOf) + (direction == Direction.UP ? 1 : -1)) * multipleOf;
}
return (direction == Direction.UP ? (int) Math.ceil((double) current / multipleOf) : (direction == Direction.DOWN ? (int) Math.floor((double) current / multipleOf) : current)) * multipleOf;
}
The variable current is the number you're rounding, multipleOf is whatever you're wanting a multiple of (i.e. round to nearest 20, nearest 10, etc), and direction is an enum I made to either round up or down.
Good luck!
Round a given number to the nearest multiple of 5.
public static int round(int n)
while (n % 5 != 0) n++;
return n;
}
You can use this method Math.round(38/5) * 5 to get multiple of 5
It can be replace with Math.ceil or Math.floor based on how you want to round off the number
Use this method to get nearest multiple of 5.
private int giveNearestMul5(int givenValue){
int roundedNum = 0;
int prevMul5, nextMul5;
prevMul5 = givenValue - givenValue%5;
nextMul5 = prevMul5 + 5;
if ((givenValue%5!=0)){
if ( (givenValue-prevMul5) < (nextMul5-givenValue) ){
roundedNum = prevMul5;
} else {
roundedNum = nextMul5;
}
} else{
roundedNum = givenValue;
}
return roundedNum;
}
if (n % 5 == 1){
n -= 1;
} else if (n % 5 == 2) {
n -= 2;
} else if (n % 5 == 3) {
n += 2;
} else if (n % 5 == 4) {
n += 1;
}
CODE:
public class MyMath
{
public static void main(String[] args) {
runTests();
}
public static double myFloor(double num, double multipleOf) {
return ( Math.floor(num / multipleOf) * multipleOf );
}
public static double myCeil (double num, double multipleOf) {
return ( Math.ceil (num / multipleOf) * multipleOf );
}
private static void runTests() {
System.out.println("myFloor (57.3, 0.1) : " + myFloor(57.3, 0.1));
System.out.println("myCeil (57.3, 0.1) : " + myCeil (57.3, 0.1));
System.out.println("");
System.out.println("myFloor (57.3, 1.0) : " + myFloor(57.3, 1.0));
System.out.println("myCeil (57.3, 1.0) : " + myCeil (57.3, 1.0));
System.out.println("");
System.out.println("myFloor (57.3, 5.0) : " + myFloor(57.3, 5.0));
System.out.println("myCeil (57.3, 5.0) : " + myCeil (57.3, 5.0));
System.out.println("");
System.out.println("myFloor (57.3, 10.0) : " + myFloor(57.3,10.0));
System.out.println("myCeil (57.3, 10.0) : " + myCeil (57.3,10.0));
}
}
OUTPUT:There is a bug in the myCeil for multiples of 0.1 too ... no idea why.
myFloor (57.3, 0.1) : 57.2
myCeil (57.3, 0.1) : 57.300000000000004
myFloor (57.3, 1.0) : 57.0
myCeil (57.3, 1.0) : 58.0
myFloor (57.3, 5.0) : 55.0
myCeil (57.3, 5.0) : 60.0
myFloor (57.3, 10.0) : 50.0
myCeil (57.3, 10.0) : 60.0