Rounding Issue with Quadratic Program - java

In a problem that I am practicing, the goal is to write the quadratic expression, then round it to the thousandths place. Here is the desired output:
1(a variable) 6(b variable) 3(c variable)
4(a variable) 10(b variable) 6.1(c variable)
Output:
-0.551, -5.449 (answer for top line)
-1.056, -1.444 (answer for bottom line)
The question is not about how to solve the problem, but instead the answers that I am getting. When computing the quadratic equation as follows:
double a = scan.nextDouble();
double b = scan.nextDouble();
double c = scan.nextDouble();
//equation is correct
double answer1 = 0.001 * Math.floor((-b + Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a)* 1000.0) ;
double answer2 = 0.001 * Math.floor((-b - Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a) * 1000.0);
The answers I am getting are correct, except when I start the rounding to the thousandths place, some numbers are right and others are not even though it looks like they are rounding correctly just not according to the problem.
My Output:
-0.551, -5.45
-1.057, -1.444
Is this something to do with how I am rounding? Any help on understanding this rounding issue would be appreciated :)

https://floating-point-gui.de/languages/java/
How to Round
To get a String:
String.format("%.2f", 1.2399) // returns "1.24"
String.format("%.3f", 1.2399) // returns "1.240"
String.format("%.2f", 1.2) // returns "1.20"
To print to standard output (or any PrintStream):
System.out.printf("%.2f", 1.2399) // same syntax as String.format()
If you don’t want trailing zeroes:
new DecimalFormat("0.00").format(1.2)// returns "1.20"
new DecimalFormat("0.##").format(1.2)// returns "1.2"
If you need a specific rounding mode:
new BigDecimal("1.25").setScale(1, RoundingMode.HALF_EVEN); // returns 1.2
And if you do need to round the actual number not just the printed output:
double result = Math.round(value * scale) / scale;
where scale might be fixed at 1000 for three decimal places or calculated for an arbitrary number of decimal places:
int scale = (int) Math.pow(10, precision);

Related

Java: method for an equation relevant to the Karplus-Strong equation does not return the anticipated result; unclear cause

In Part 1 of a prompt, I am expected to integrate an equation into Java to get the value for a period (T). The equation is as follows: T = FS / (440 * (2 ^(h/12))
NOTE:
FS = sample rate, which is 44100 / 1.
h = halfstep, which is provided by the user.
An example of this equation is: 44100 / (440 * (2 ^(2/12)) = 89.3
The code I wrote is as follows:
public static double getPeriod(int halfstep) {
double T = 100; // TODO: Update this based on note
double FS = 44100 / 1;
double power = Math.pow(2, (halfstep / 12));
double denominator = 440 * (power);
double result = (FS) / (denominator);
T = Math.round(result);
return T;
}
// Equation test.
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("halfstep is: ");
int halfstep = in.nextInt();
double period = getPeriod(halfstep);
System.out.print("Period: " + period + " ");
}
But when I run through this code with h = 2, T = 100.0 instead of the anticipated 89.3 and I am not sure what the issue is. Any thoughts on what's going on?
Because halfStep is an int, when you write
(halfstep / 12)
the calculation is done by taking halfStep / 12 and rounding down to the nearest integer. As a result, if you plug in 2 here, then halfStep / 12 will come back as 0 instead of 1/6. That's messing up the computation and is likely what's giving you the wrong answer.
You have a few options for how to proceed here. One would be to change halfStep to be a double rather than an int. Another would be to rewrite the division as
halfStep / 12.0
which, since 12.0 is a double literal, will perform the division in the way you intend.
One other potential issue - you declare the variable T as 100.0, but never use T anywhere in the calculation and ultimately overwrite it before returning it. I'm not sure whether this is intentional or whether that indicates that one of the formulas is incorrect.
Hope this helps!

How do I get rid of a few decimal points in java? [duplicate]

This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
Closed 3 years ago.
I have this program that resembles a fight and each attack does a random damage amount from a range of two numbers, eg., an attack can do damage from 60ish to 70ish. I say 'ish' because everytime I display the damage amount, it gives a really big decimal number like 70.28326772002643.
I want to know how to make it so that it still displays decimals, but much less, like 70.28. How do I do this?
This is not a duplicate because the other question has python syntax, and I want to know how to do it in Java.
Also, it is not a duplicate because my type is a double, not a float.
The following will do the trick for you:
public class Main {
public static void main(String[] args) {
double d1=70.28326772002643;
double d1rounded=Math.round(d1 * 100.0) / 100.0;
System.out.println(d1rounded);
double d2=70.28726772002643;
double d2rounded=Math.round(d2 * 100.0) / 100.0;
System.out.println(d2rounded);
}
}
Output:
70.28
70.29
I also recommend you check How to round a number to n decimal places in Java for some better ways.
Let's say your output is double output = 70.28326772002643;
Do,
DecimalFormat deci = new DecimalFormat("#.00");
double newOutput = deci.format(output);
newOutput will be equal to 70.28
Use the printf method, or String.format:
> double d = 1.23456;
> System.out.printf("%.2f\n", d);
1.23
> System.out.printf("%.3f\n", d);
1.235
> String.format("%.2f", d);
"1.23" (String)
> String.format("%.3f", d);
"1.235" (String)
round() function can convert from double to integer, you can multiply 100 and then divide 100 to get 2 decimal place.
double pi = Math.PI;
double pi_round = 0.01* Math.round(pi * 100);
System.out.println(pi_round);

Cosine Law for inside angles

I'm trying to create a program in Java to calculate the inside angles of any triangle when the user inputs the side lengths. I've seen a few questions similar to this but I can`t get mine to work.
I want this to calculate the angle in degrees but it keeps giving me the wrong answer or not a number (NaN). I've tried putting it all in to one equation in case it was just rounding errors but it just gave the same answer. I've since put it back into this format to make it easier to read.
public class Triangles
{
// variables already declared and user inputs double sideOne, sideTwo, sideThree
threeSq=sideThree*sideThree;
twoSq=sideTwo*sideTwo;
oneSq=sideOne*sideOne;
public static double getAngleOne(double oneSq, double twoSq, double threeSq, double sideOne, double sideTwo, double sideThree)
{
double angOne;
angOne = (oneSq + twoSq - threeSq) / (2 * sideOne * sideTwo);
angOne = Math.toRadians(angOne);
angOne = Math.acos(angOne);
angOne = Math.toDegrees(angOne);
return angOne;
}
public static double getAngleTwo(double oneSq, double twoSq, double threeSq, double sideOne, double sideTwo, double sideThree)
{
double angTwo;
angTwo = (twoSq + threeSq - oneSq) / (2 * sideTwo * sideThree);
angTwo = Math.toRadians(angTwo);
angTwo = Math.acos(angTwo);
angTwo = Math.toDegrees(angTwo);
return angTwo;
}
public static double getAngleThree(double oneSq, double twoSq, double threeSq, double sideOne, double sideTwo, double sideThree)
{
double angThree;
angThree = (oneSq + threeSq - twoSq) / (2 * sideOne * sideThree);
angThree = Math.toRadians(angThree);
angThree = Math.acos(angThree);
angThree = Math.toDegrees(angThree);
return angThree;
}
}
I`m using the cosine law, but it is not giving me the correct answer. For example, when I input the side lengths as 3, 3 and 3 it gives me 71.68993312052173; when I input 5, 6 and 7 (sides 1, 2 and 3 respectively), I get NaN.
edit:
Thanks for the advice, I have changed all the ints to doubles and my math was the problem (forgot brackets around the oneSq + twoSq - threeSq)
I put up the full revised code but it is still giving the wrong answer, for a triangle with all sides the same, it should return 60 for all three but it`s returning 89.49999365358626.
After correcting the computation of the ratios there still remains one thing to do: Lose the lines
angOne = Math.toRadians(angOne);
at this point, angOne does not contain any angle. If the sides obey the triangle inequality, angOne should at that point contain a number between -1 and 1 that does not need converting.
The ratio of the areas for an equilateral triangle is 0.5. The operations convert-to-radians, acos, convert-to-degrees can be combined as
M*acos(x/M) = M*(pi/2-asin(x/M)),
with the multiplier M=180/pi. Since x/M is small, the result is approximately
M*(pi/2-x/M)=90-x,
resulting in a value close to 89.5, as obtained in your last trial.
Of course, the desired result is M*acos(0.5)=M*(pi/3)=60.
Apart from not using double values, your calculations are probably not correct.
According to cosine law
cosγ = (a^2 + b^2 - c^2)/2ab
so change ang = oneSq + threeSq - twoSq / (2 * sideOne * sideThree); to
double ang = (oneSq + twoSq - threeSq)*1.0 / (2 * sideOne * sideTwo);

Unable to understand how rounding is working for decimal digits (Java)

While working on one implementation, i saw difference in amount being shown at 2 places.While doing some more debugging i found this information.
I have 2 decimal values and both getting rounded to 2 decimal places.
double value =1091.225;
double value1 =48.125;
System.out.println((double)Math.round(value * 100) / 100);
System.out.println((double)Math.round(value1 * 100) / 100);
BigDecimal price = new BigDecimal(value);
price = price.setScale(2, RoundingMode.UP);
double val= ((long) (value < 0 ? value * 100 - 0.5 : value * 100 + 0.5)) / 100.0;
BigDecimal price1 = new BigDecimal(value1);
price1 = price1.setScale(2, RoundingMode.UP);
double val1= ((long) (value1 < 0 ? value1 * 100 - 0.5 : value1 * 100 + 0.5)) / 100.0;
System.out.println(val);
System.out.println(val1);
These are results
1091.22
48.13
1091.22
48.13
However if i change values to
double value =1091.255;
double value1 =48.125;
Results are different
1091.26
48.13
1091.26
48.13
Can anyone please help me to understand as why this is happening?
It's because of the way floating point numbers are stored in memory. The value 1091.225, and 1091.255d, don't have exact binary representation. Try printing their value using the below statements:
System.out.println(new BigDecimal(1091.225d));
System.out.println(new BigDecimal(1091.255d));
Output will be:
1091.22499999999990905052982270717620849609375
1091.2550000000001091393642127513885498046875
It's clear that the first one will be rounded to .22, and 2nd one to .26.
This is caused because decimal values are not stored as precise values, and you are discarting decimal part by casting to long.
Try this to better understand:
System.out.println(value * 100 + 0.5);
System.out.println((long)(value * 100 + 0.5));
This prints
109122.99999999999
109122
So divided by 100.0 it is 1091.22
But for other values it prints
109126.00000000001
109126
So divided by 100.0 it is 1091.26
Math.round() is the issue here.
public static int round(float a) Returns the closest int to the
argument. The result is rounded to an integer by adding 1/2, taking
the floor of the result, and casting the result to type int. In other
words, the result is equal to the value of the expression:
(int)Math.floor(a + 0.5f)
Hope this helps.
Also, note that the precision for decimal point values are not accurate, since they cannot be represented perfectly in binary form.
This should help.

rounding decimal points [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Round a double to 2 significant figures after decimal point
I am trying to work with converting a decimal degree (23.1248) into a minutes style degree(23 7'29.3").
this is what I have so far:
double a=23.1248;
int deg=(int)a;//gives me the degree
float b=(float) (a-deg);
int min=(int) (b*60);//gives me the minutes
double sec= (double) ((c*60)-min);//gives me my seconds
everything works fine, but I would like to round the seconds up to either the nearest tenth or hundrenth. I have looked at decimal formatting, but would prefer not to cast it to a string. I have also looked at bigdecimal but do not think that would be helpful,
Try using Math.round(double) on the number after scaling it up, then scaling it back down.
double x = 1.234;
double y = Math.round(x * 100.0) / 100.0; // => 1.23
You can also use BigDecimal if you want to get really heavyweight:
BigDecimal a = new BigDecimal("1.234");
BigDecimal b = a.setScale(2, RoundingMode.DOWN); // => BigDecimal("1.23")
First off, there are library functions to do this, so why not just use those? See Math.round(). No need to reinvent the wheel. If you wanted to, though, you could try what follows. To round a double to the hundredth's place:
x = 0.01 * floor(x * 100.0)
To round a double to the tenth's place:
x = 0.1 * floor(x * 10.0)
To round a double to the 10^k place:
x = 10^k * floor(x / 10^k)
The implementation in any language - including Java - should be straightforward. A problem with this is that it doesn't really round, but truncates, to your position. To fix this, you can simply add 0.5 * 10^k to your number before rounding. If you just want to round up, use the versions above, and add 10^k before or after the computation.

Categories

Resources