I have two values and I am trying to compare them, but getting the worng results:
public void subtotal() throws Exception {
WebDriverWait wait = new WebDriverWait(session.driver, 100);
double subtotal_price = 0;
DecimalFormat decimal = new DecimalFormat("0.00");
WebElement subtotal = wait.until(ExpectedConditions.visibilityOf( element("Subtotal_cart")));
Float subtotal_value = Float.parseFloat(subtotal.getText().substring(1));
logger.info("subtotal_value"+subtotal_value);
File file = new File("ItemUPC/ItemUPC.txt");
Scanner sc = new Scanner(file);
while (sc.hasNextLine()) {
String[] line = sc.nextLine().split("[|]");
String price = line[2];
subtotal_price = subtotal_price + Double.parseDouble(price);
}
logger.info("subtotal_price"+subtotal_price);
if ((subtotal_value)==(subtotal_price))
{
logger.info("Subtotals updated");
}
else
{
logger.info("Subtotals not updated");
}
}
The following is the ItemUPC file:
2|BATH BENCH|19.00
203|ORANGE BELL|1.78
When I print the value of subtotal_price and Subtotal_value I am getting both as 20.78, but when its getting compared in the if statement, I am getting output as "Subtotals not updated"
Not sure where I am getting wrong. Can someone please help? Thank you.
Comparing floating point numbers can be challenging, due to differences in precision between floating point types and their binary representations of decimal numbers.
You have two simple options:
Compare the absolute value of the difference between the two values to an epsilon, or threshold, value
Use BigDecimal as a substitute for your Float and double variable types
Example 1:
// simplification that may fail in certain edge cases
static final double EPSILON = .001; // acceptable error - adjust to suit your needs
if (Math.abs(subtotal_price - subtotal_value) < EPSILON) {
logger.info("Subtotals updated");
}
// ...
Example 2:
BigDecimal subtotal_price = new BigDecimal("0");
// ...
BigDecimal subtotal_value = new BigDecimal(subtotal.getText().substring(1));
// ...
if(subtotal_price.compareTo(subtotal_value) == 0) {
logger.info("Subtotals updated");
}
// ...
Related
I am writing a java gui program which converts different units of measurement. I want to limit the output of the result to two decimal place so it looks neater however i have been struggling to get it to work. Below is my code please can someone help.
if (text.isEmpty() == false) {
double value = Double.parseDouble(text);
// the factor applied during the conversion
double factor = 0;
// the offset applied during the conversion.
double offset = 0;
// Setup the correct factor/offset values depending on required conversion
switch (combo.getSelectedIndex()) {
case 0: // inches/cm
factor = 2.54;
break;
case 1: // miles/km
factor = 1.60;
break;
case 2: // pounds/kilograms
factor = 0.45;
break;
case 3: // gallons/Litres
factor = 4.54;
break;
case 4: // feet/meters
factor = 0.30;
break;
case 5: // celsius/kelvin
factor = 1;
offset=273.15;
break;
case 6: // acres/hectare
factor = 2.471;
break;
}
double result = 0;
if(reverseCheck.isSelected() == true) {
result = factor / value - offset;
}else {
result = factor * value + offset;
}
count++;
labelCount.setText("Conversion Count: "+count);
label.setText(Double.toString(result));
DecimalFormat decFormat = new DecimalFormat("0.00");
decFormat.format(result);
I am new to programming so if you could please explain why this code isn't functional then that would be much appreciated. My output currently is too many decimal places and i need it to only be 2 decimal places.
I am new to programming
So the first thing you need to learn is how to simplify the problem.
I want to limit the output of the result to two decimal place so it looks neater
So, forget about the rest of your application and learn how to do exactly that:
double value = 123.45678;
DecimalFormat decFormat = new DecimalFormat("0.00");
String formatted = decFormat.format(value);
System.out.println( formatted );
I am writing a java gui program which converts different units of measurement.
That is irrelevant to you question. As you can see from the above example you first test a new concept with hardcoded data.
Once you get that working, then you worry about the mathematical calculations to dynamically get the "value" that you want to format.
My output currently is too many decimal places
label.setText(Double.toString(result));
DecimalFormat decFormat = new DecimalFormat("0.00");
decFormat.format(result);
Do you see the problems with the above code?
you set the text of the label BEFORE you format the result
you don't assign the formatted text to a variable so that last statement doesn't do anything.
I know, there are dozens of topic like this in site but I am having trouble with 3 problems and I couldnt figure out all of them at the same time.
Actually, I am trying to make a calculator for Android but sometimes I cannot get what I am expected to.
A part of my code is;
}else if(operator.equals("/")){
if(resultScreen.indexOf("/")==0){
strNum2 = resultScreen.substring(resultScreen.indexOf("/")+1,resultScreen.length());
intNum1 = result;
}else{
strNum1 = resultScreen.substring(0,resultScreen.indexOf("/"));
strNum2 = resultScreen.substring(resultScreen.indexOf("/")+1,resultScreen.length());
intNum1 = new BigDecimal(strNum1);
}
intNum2 = new BigDecimal(strNum2);
if(intNum2.equals(0)){
tvScreen.setText("Err");
resultScreen ="";
}else{
result = intNum1.divide(intNum2);
resultScreen = result.toString();
tvScreen.setText(resultScreen);
resultScreen ="";
}
}
When I try to;
22/7
It comes up;
3
How can I fix that?
By the way, I want to keep the exact value of decimal.
This works
BigDecimal a = new BigDecimal("22");
BigDecimal b = new BigDecimal("3");
BigDecimal res = a.divide(b, 2, RoundingMode.HALF_UP);
System.out.println(res);
The key thing is to have a roundingMode else if the value can not be represented exactly an Exception will be thrown.
Complete newbie here guys. I'm working on a Java program to prompt the user for 3 variables which are used to calculate a future investment's value. Everything works perfectly, except when it comes time to put both my datatypes into ONE array.
Here's what the output SHOULD look like:
Year Future Value
1 $1093.80
2 $1196.41
3 $1308.65
...
This is what mine looks like:
Year 1
Future Value 1093.81
Year 2
Future Value 1196.41
Year 3
Future Value 1308.65
...
My year is an int value and my Future value is a double (rounded). I've been sitting here racking my brain and all the forums I can find and haven't been successful. Every time I put both value into an array I get an error about putting two different datatypes together. Any insight would be greatly appreciated. Below is the code for my full program:
import java.util.Scanner;
class investmentValue {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.print("Enter investment amount: $");
double i = s.nextDouble();
System.out.print("Enter percentage rate: ");
double r = s.nextDouble()/100;
System.out.print("Enter number of years: ");
int y = s.nextInt();
for (y=1; y<=30; y++) {
double f = futureInvestmentValue(i,r,y);
System.out.println("Year " + y);
System.out.println("Future Value " + f);
}
}
public static double futureInvestmentValue (double investmentAmount, double monthlyInterestRate, int years){
double value=1;
value = investmentAmount*Math.pow((1+(monthlyInterestRate/12)),(years * 12));
double roundValue = Math.round(value*100.0)/100.0;
return roundValue;
}
}
One solution is to start by implementing a pad function. Something like,
public static String pad(String in, int len) {
StringBuilder sb = new StringBuilder(len);
sb.append(in);
for (int i = in.length(); i < len; i++) {
sb.append(' ');
}
return sb.toString();
}
Now we can combine that with String.format() to get the dollars and cents, use a consistent printf() for the header and output lines. To get something like,
// Print the header.
System.out.printf("%s %s%n", pad("Year", 12), "Future Value");
for (int y = 1; y <= 30; y++) {
String year = pad(String.valueOf(y), 13); // <-- One more in your alignment.
String fv = String.format("$%.2f", futureInvestmentValue(i,r,y));
System.out.printf("%s %s%n", year, fv);
}
The System.out.println command isn't the only method available to you!
Try this in your loop:
System.out.print(y); // note that we use print() instead of println()
System.out.print('\t'); // tab character to format things nicely
System.out.println(f); // ok - now ready for println() so we move to the next line
Naturally, you'll want to do something similar to put your headings in.
PS - I'm pretty sure this is just an output formatting question - you don't really want to put all these values into a single array, right?
Given that you really are looking for formatted output, it may be better to use the printf() method.
The following inside the loop (instead of the 3 lines I wrote above) should do the trick (untested - I haven't used printf() format strings in a long, long time).
System.out.printf("%i\t$%0.2f", y, f);
EDIT: edited to answer your question in the comments about constructors... You should also check out this for further understanding
You could create a class that will hold both of the arrays...
This would give you a single object, let's call it StockData, that holds two arrays for the two separate types you need. You need to create the object once and then insert the data separately by type.
class StockData {
double[] data1;
int[] data2;
// default constructor
StockData() {
}
// constructor
StockData(double[] data1, int[] data2) {
this.data1 = data1;
this.data2 = data2;
}
// getters, setters...
}
Then you add data to an array of its type:
// using default constructor to add a single value to both arrays
StockData sd = new StockData();
sd.data1[INDEX_X] = YOUR_DOUBLE;
sd.data2[INDEX_X] = YOUR_INT;
// using default constructor to add all data to both arrays
StockData sd = new StockData();
sd.data1 = YOUR_ARRAY_OF_DOUBLE;
sd.data2 = YOUR_ARRAY_OF_INTS;
// using constructor to add all array data directly
StockData sd = new StockData(YOUR_ARRAY_OF_DOUBLE, YOUR_ARRAY_OF_INTS);
You could also have an object that will hold the double and int value, so the object will represent a single stock information of 2 values and then create an array containing those objects...
class StockData {
double data1;
int data2;
// default constructor same as before
// constructor
StockData(double data1, int data2) {
this.data1 = data1;
this.data2 = data2;
}
// getters, setters...
}
// ...
Adding data:
// create an array of StockData objects
StockData[] sd = new StockData[TOTAL_AMOUNT_OF_DATA];
// ... obtain your data
// using default constructor to add a single value to the array
sd[INDEX_X] = new StockData();
sd[INDEX_X].data1 = YOUR_DOUBLE;
sd[INDEX_X].data2 = YOUR_INT;
// using constructor to add all data directly
sd[INDEX_X] = new StockData(YOUR_DOUBLE, YOUR_INT);
If you want the program to have an specific format you could try to change your code and put this where your for is:
System.out.println("Year Future Value");
for (y=1; y<=30; y++) {
double f = futureInvestmentValue(i,r,y);
System.out.print(y);
System.out.println(" " + f);
}
this way you will have your output in the format you need without using arrays. But if you want to do an array for this you could declare an array of objects and create a new object with two attributes (year and future value)
Also your class name is investmentValue and it is recommended that all classes start with upper case it should be InvestmentValue
I hope that this can help you
A fun data structure you would be able to use here is a Map (more specifically in Java, a HashMap). What you are doing is associating one value with another, an integer to a double, so you could make something that looks like this:
Map<Integer, Double> myMap = new HashMap<>();
This would take the year as the integer, and the double as the price value, and you could iterate over the map to print each value.
Additionally if you really are looking for a "multidata type array," Java automatically casts from integer to double should you need to. For example:
int i = 2;
double[] arr = new double[2];
arr[0] = 3.14
arr[1] = i;
The above code is perfectly valid.
I was doing a simple calculation program in java when I encountered this problem. I want to convert centimeter square to meter square. 1 cm² = 0.0001 m². When i create the program in java to do this conversion I got result in '1.0E-4' instead of '0.0001'. I don't know why it is showing in that way. may someone guide me how to do it or something that may help
Here is the code:
import java.io.*;
class First {
public static void main(String x[]) {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Please Enter the number");
double number = Double.parseDouble(br.readLine());
double d1 = 0.0001;
double result = number * d1;
System.out.println("Result is " + result);
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
Doubles within a certain range are printed as a base and an exponent using the scientific notation.
1.0E-4 simply means 1 * 10^(-4), or 0.0001, so the answer you're getting is correct. As suggested by Smutje, you can change the way in which doubles are printed, like this.
I have an assignment and I need to get an input from the user to refine an answer to an x(the input of the user) number of decimal places. I'm going to refine my answer until there aren't any changes in the x decimal place.Can you please help on how I could achieve this answer?
It's not very clear what you are trying to achieve, but I think you want to accept a number and then round it up as the user specifies it.
Java's BigDecimal http://docs.oracle.com/javase/1.5.0/docs/api/java/math/BigDecimal.html class has all the functions you may need for this purpose. Please don't use the primary data types (float, double) as they will result in rounding errors sooner or later.
While it is true what #Thihara answers, maybe you need a bit simpler approach. Unless you need the precision of BigDecimal, you can do this:
int x = 4;
double value = 3.141593;
long answer = (long) (value * Math.pow(10, x));
The point is: multiply the value by 10^x and then convert to long (or int). Of course, this only works for small x.
There are a bunch of issues floating around here, that you should be aware of.
The first is that if you use a floating point number to represent your answer, you cannot represent every possible real number so you almost definitely will get rounding errors. Check out http://floating-point-gui.de/ for great information about this.
Secondly, when you print a float or double value, Java does some magic with it so that it looks nice. See Float.toString(float) and Double.toString(double) for more information.
So in reality, if you enter
double answer = 3.14159265;
it is stored as
3.141592650000000208621031561051495373249053955078125
which you can see using
System.out.println(new BigDecimal(answer));
So assuming you get your answer as a double (or float), you should use BigDecimal's setScale method. Also, if you want to limit the decimal places that your user can choose to the number visible when you print the double as a string, pass String.valueOf(answer) to BigDecimal's constructor.
Here is a little program that demonstrates how to do this
public static void main(String[] args) {
double answer = 3.14159265;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String input = null;
do {
System.out.println("Answer: " + answer);
System.out.println("How many decimal places do you want? ");
try {
input = in.readLine();
} catch (IOException e) {
e.printStackTrace();
}
if (input != null) {
try {
int decimalPlaces = Integer.parseInt(input);
if (decimalPlaces < 0) {
System.out.println("Enter a positive value.");
} else {
BigDecimal scaled = new BigDecimal(
String.valueOf(answer));
if (decimalPlaces > scaled.scale()) {
System.out
.println("Answer does not have that many decimal places.");
} else {
scaled = scaled.setScale(decimalPlaces,
RoundingMode.HALF_EVEN);
System.out.println("Rounded answer: " + scaled);
}
}
} catch (Exception e) {
System.out.println("Not a valid number.");
}
}
} while (input != null);
}
Most of the code is error/input checking. The real work is done by setScale. Just keep in mind that there are many boundary conditions when working with floating point numbers, and you should be good!