Decimal format not limiting values to two decimal places - java

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.

Related

Comparing two values in Java

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");
}
// ...

How to convert double values to string in a text field

I want to do the average of 9 textfields and also the sum of them and place them in 2 other textfields by using a button, currently this code doesnt displays anything in the other textfiels. If i put anything, for example "A" instead of "%.Of" it would display the "A" in the textfield but not the average or the sum. Please i need help with a code that would work, dont mind if i need to change a lot.
This is what im working with:
private void jButton_RankingActionPerformed(java.awt.event.ActionEvent evt) {
double R[] = new double [14];
R[0] = Double.parseDouble(jTextField_Math.getText());
R[1]= Double.parseDouble(jTextField_English.getText());
R[2] = Double.parseDouble(jTextField_Spanish.getText());
R[3] = Double.parseDouble(jTextField_Biology.getText());
R[4] = Double.parseDouble(jTextField_Physics.getText());
R[5] = Double.parseDouble(jTextField_Chemestry.getText());
R[6] = Double.parseDouble(jTextField_PE.getText());
R[7] = Double.parseDouble(jTextField_Humanities.getText());
R[8] = Double.parseDouble(jTextField_Technology.getText());
R[9] = (R[0]+R[1]+R[2]+R[3]+R[4]+R[5]+R[6]+R[7]+R[8])/ 9;
R[10] = R[0]+R[1]+R[2]+R[3]+R[4]+R[5]+R[6]+R[7]+R[8];
String Average = String.format("%.Of",R[9]);
jTextField_Average.setText(Average);
String TotalScore = String.format("%.Of",R[10]);
jTextField_TotalScore.setText(TotalScore);
if(R[10]>=50)
{
jTextField_Ranking.setText("Superior");
}
else if (R[10]>=41){
jTextField_Ranking.setText("Alto");
}
else if (R[10]>=34){
jTextField_Ranking.setText("Basico");
}
else if (R[10]<=33){
jTextField_Ranking.setText("Bajo");
Since you mentioned that an A would print, it follows that jButton_RankingActionPerformed is being called. The issue you have is the format string you are using to print the total and average. You have mistakenly chosen the capital letter O rather than the number zero.
Replace this (which contains a capital letter O):
String.format("%.Of",R[9]);
With
1) No decimal will be printed: i.e. 50.2 would be 50
String.format("%.0f",R[9]);
2) Or perhaps you want to see one decimal place like 50.2
String.format("%.1f",R[9]);
Also a very small optimization is:
R[9] = (R[0]+R[1]+R[2]+R[3]+R[4]+R[5]+R[6]+R[7]+R[8])/ 9;
R[10] = R[0]+R[1]+R[2]+R[3]+R[4]+R[5]+R[6]+R[7]+R[8];
Could be replaced with:
R[10] = R[0]+R[1]+R[2]+R[3]+R[4]+R[5]+R[6]+R[7]+R[8];
R[9] = R[10] / 9;
or use a loop to calculate R[10]. (to add R[0] to R[8])

How to enter Double values in case statement in java [duplicate]

This question already has answers here:
switch expression can't be float, double or boolean
(6 answers)
Closed 5 years ago.
I used to check int values in case statements but is there any way check double values too? I can't use If else. This is an assignment. Thank you.
yes, but it won't perform very well. This will work
// don't do this, unless you want readability not performance.
switch(Double.toString(d)) {
case "1.0":
break;
case "Infinity":
break;
}
Instead you should use a series of if/else statements or use a Map<Double, DoubleConsumer> for a long list of doubles.
You can use a NavigableMap for efficient range searches.
NavigableMap<Double, DoubleConsumer> map = new TreeMap<>();
// default value is an assertion error
map.put(Double.NEGATIVE_INFINITY, d -> new AssertionError(d));
double upperBound = 12345;
map.put(upperBound, d -> new AssertionError(d));
// if >= 1.0 then println
map.put(1.0, System.out::println);
public static void select(NavigableMap<Double, DoubleConsumer> map, double d) {
Map.Entry<Double, DoubleConsumer> entry = map.floorEntry(d);
entry.getValue().accept(d);
}
Since double values provide an exact representation only in case when the value can be expressed as a sum of powers of 2 that located "close enough" to each other (within the length of mantissa), and because switch works only with exact matches, you cannot use doubles in a switch in a general case.
The basic reason for it is the same as the need to be careful when using == to compare doubles. The solution is the same as well: you should use a chain of if-then-else statements to find the desired value
if (a <= 0.2) {
...
} else if (a < 0.5) {
...
} else if (a < 0.9) {
...
} else {
...
}
or use a TreeMap<Double,Something> and perform a limit search:
TreeMap<Double,Integer> limits = new TreeMap<Double,Integer>();
limits.put(0.2, 1);
limits.put(0.5, 2);
limits.put(0.9, 3);
...
Map.Entry<Double,Integer> e = limits.ceilingEntry(a);
if (e != null) {
switch(e.getValue()) {
case 1: ... break;
case 2: ... break;
case 3: ... break;
}
}
Switch cases only take byte, short, char, and int. And a few other special cases.
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html

How are "ranges" defined in Java?

I have a chunk of code that needs to determine if a given integer is between a set of other integers. I'd also like to have this in a case statement so as to not have a surplus of if..else statements everywhere. Here's a bit of the code:
switch (copies) {
case copies >= 0 && copies <= 99: copyPrice = 0.30; break;
case copies >= 100 && copies <= 499: copyPrice = 0.28; break;
case copies >= 500 && copies <= 749: copyPrice = 0.27; break;
case copies >= 750 && copies <= 1000: copyPrice = 0.26; break;
case copies > 1000: copies = 0.25; break;
}
where copies is an integer and copyPrice is a double. I get several errors saying that it expects to receive a integer but gets a boolean instead. What is the best (or optimal) way of setting this up? Any help is greatly appreciated!
This line (and similar):
case copies >= 0 && copies <= 99:
Returns a compiler error since it gives a boolean but the compiler expects an int since copy is declared as int.
One way to solve this is using an array with the desired ranks, and have a switch statement for the index found:
public double calculateCopyPrice(int copies) {
int[] range = { 99, 499, 749, 1000 };
double copyPrice = 0;
int index = -1;
for (int i = 0; i < range.length; i++) {
if (range[i] >= copies) {
index = i;
break;
}
}
switch (index) {
case 0: copyPrice = 0.30; break;
case 1: copyPrice = 0.28; break;
case 2: copyPrice = 0.27; break;
case 3: copyPrice = 0.26; break;
default: copyPrice = 0.25; break;
}
//probably more logic here...
return copyPrice;
}
After some tests, I've found a more flexible solution using a TreeMap<Integer, Double> which allows you to have a specie of range (what you're looking for) and ease the search by using TreeMap#ceilingEntry:
//TreeMap to store the "ranges"
TreeMap<Integer, Double> theMap = new TreeMap<Integer, Double>();
//add the data
theMap.put(99, 0.3);
theMap.put(499, 0.28);
theMap.put(749, 0.27);
theMap.put(1000, 0.26);
//the "default" value for max entries
theMap.put(Integer.MAX_VALUE, 0.25);
//testing the solution
Double ex1 = theMap.ceilingEntry(50).getValue();
Double ex2 = theMap.ceilingEntry(500).getValue();
Double ex3 = theMap.ceilingEntry(5000).getValue();
Double ex4 = theMap.ceilingEntry(100).getValue();
System.out.println(ex1);
System.out.println(ex2);
System.out.println(ex3);
System.out.println(ex4);
java has no native concept of "ranges", let alone support for them in case statements.
usually, when faced with this kind of logic i personally would do one of 2 things:
just have a chain of if-else statements. doesnt even habe to be a chain:
public static double calculateCopyPrice(int copies) {
if (copies > 1000) return 0.25;
if (copies >= 750) return 0.26;
//etc
}
this code has no "else" branches and is just as much typing as the switch syntax you'd like. possibly even less (i only check a single bound every time)
you could use an enum, say:
public enum Division {UNDER_100, 100_to_500, ... }
and then :
Division division = categorize(copies);
switch (division) {
case UNDER_100:
//etc
}
but this is serious overkill for what youre trying to do. i'd use that if this division is also useful elsewhere in your code.
Switch case function must have an exact number in case. For example:
case 0:
case 1:
You're trying to use case from some value to some value and it's not implemented that way in Java. For your problem, you must use if-else statement since it's impossible to do it with switch case. Hope it helped.
Look the problem is very basic..
In a switch statement it allows only the following datatypes and wrapper classes
Byte,short,char,int,Byte,Short,Character,Integer,enum,String..
If you are passing anything other than that will give you an error.
In your case the condition which you are evaluating will give you result which is a Boolean value.
NavigableMap.seilingEntry() may be a good solution in many cases,
but in other cases the following may be clearer:
double getPrice(int copies){
return copies>1000 ? 0.25
: copies>750 ? 0.26
: copies>500 ? 0.27
: copies>100 ? 0.28
: copies>0 ? 0.30
: 0; // or check this condition first, throwing an exception
}

Refining an answer to x decimal places in java

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!

Categories