Suppose I have the following code:
double median = med(10.0, 12.0, 3.0); //method returns middle number as double
Now, I want to write a message stating the median. Can this be done using println(), like the following:
System.out.println("Your number was " + median);
Or must I use printf() with double values?
The reason I ask is because I have seen both practices online 1, but when I try using println() I get an error, unless i write:
System.out.println(median);
Hence, can you use println() to print out double values and strings, or must you use printf() for that purpose?
The printf method can be particularly useful when displaying multiple variables in one line which would be tedious using string concatenation:
The println() which can be confusing at times. (Although both can be used in almost all cases).
double a = 10;
double b = 20;
System.out.println("a: " + a + " b: " + b);// Tedious string concatenation.
System.out.printf("a: %f b: %f\n", a, b);// Output using string formatting.
Output:
a: 10.0 b: 20.0
a: 10,000000 b: 20,000000
You can do both (if System.out.println("Your number was " + median); is not working you have something else wrong. Show us the stack trace). printf allows you some more formatting options (such as the number of decimal places) without having to use a DecimalFormat, but it is a choice on style rather than anything else.
Personally I find string concatenation easer on the eyes and easer to maintain. The %blah gets lost in the string, errors in string concatenation is a compile time error and adding a new variable requires less thought. However I'm in the minority on this.
The pros in printf is that you don't need to construct a bunch of formatters, others find its format easer on the eyes and when using a printf like method provided by a logging framework the string building only happens if actually required.
double value = 0.5;
System.out.println("value: " + value);
System.out.printf("value: %f", value);
If you want to set a number of decimal places:
double value = 0.5;
// String concatenation
DecimalFormat df = new DecimalFormat("0.000");
System.out.println("value: " + df.format(value));
// printf
System.out.printf("value: %.3f", value);
Related
I need to convert this two strings "0.0000000" and "0.0000008" to BigDecimal without losing trailing 0s.
I tried String.format
String format = "%." + precision + "f";
BigDecimal divisor = new BigDecimal(Math.pow(10, precision));
formattedAmount = amountValue.divide(divisor).setScale(precision, BigDecimal.ROUND_DOWN);
String str= String.format(format, formattedAmount);
System.out.println(str);
BigDecimal strb = new BigDecimal(str);
System.out.println(strb);
I am expecting these two strings "0.0000000" and "0.0000008" to be returned as BigDecimal without exponent like 0.0000000 and 0.0000008. But i am getting 0E-7 and 8E-7.
I need 0.0000000 and 0.0000008 as BigDecimal not as String.
When you're trying to print BigDecimal in System.out.println(strb) the toString() method on strb object will be invoked. So the output in console is also string.
See more The connection between 'System.out.println()' and 'toString()' in Java
So the only way to tell the java not to use exponent here System.out.println(strb) is to change toString() method. You can't change it directly, but you could create your own class that extends BigDecimal and override toString() method you need. Obviously it doesn't make sense.. just use toPlainString() method. From java doc:
return a string representation of this {#code BigDecimal} without an exponent field.
First of all, no matter how you output the value of a BigDecimal, it stays the same in an instance of it (as long as you don't do calculations on it).
However, the output may differ a lot.
Here are the methods BigDecimal is offering
public static void main(String[] args) {
String zero = "0.0000000";
String zeroDotsEight = "0.0000008";
BigDecimal z = new BigDecimal(zero);
BigDecimal zE = new BigDecimal(zeroDotsEight);
// play around with the precision and have a look at the output
int precision = 7;
System.out.println("String:\t\t\t\t\t" + zero);
System.out.println("BigDecimal:\t\t\t\t" + z.setScale(precision, BigDecimal.ROUND_DOWN));
System.out.println("BigDecimal.toString():\t\t\t"
+ z.setScale(precision, BigDecimal.ROUND_DOWN).toString());
System.out.println("BigDecimal.toPlainString():\t\t"
+ z.setScale(precision, BigDecimal.ROUND_DOWN).toPlainString());
System.out.println("BigDecimal.toEngineeringString():\t"
+ z.setScale(precision, BigDecimal.ROUND_DOWN).toEngineeringString());
System.out.println("BigDecimal.doubleValue():\t\t"
+ z.setScale(precision, BigDecimal.ROUND_DOWN).doubleValue());
System.out.println("————————————————————————————————————————————————————————————————");
System.out.println("String:\t\t\t\t\t" + zeroDotsEight);
System.out.println("BigDecimal:\t\t\t\t" + zE.setScale(precision, BigDecimal.ROUND_DOWN));
System.out.println("BigDecimal.toString():\t\t\t"
+ zE.setScale(precision, BigDecimal.ROUND_DOWN).toString());
System.out.println("BigDecimal.toPlainString():\t\t"
+ zE.setScale(precision, BigDecimal.ROUND_DOWN).toPlainString());
System.out.println("BigDecimal.toEngineeringString():\t"
+ zE.setScale(precision, BigDecimal.ROUND_DOWN).toEngineeringString());
System.out.println("BigDecimal.doubleValue():\t\t"
+ zE.setScale(precision, BigDecimal.ROUND_DOWN).doubleValue());
}
and this is the output on my system
String: 0.0000000
BigDecimal: 0E-7
BigDecimal.toString(): 0E-7
BigDecimal.toPlainString(): 0.0000000
BigDecimal.toEngineeringString(): 0.0E-6
BigDecimal.doubleValue(): 0.0
————————————————————————————————————————————————————————————————
String: 0.0000008
BigDecimal: 8E-7
BigDecimal.toString(): 8E-7
BigDecimal.toPlainString(): 0.0000008
BigDecimal.toEngineeringString(): 800E-9
BigDecimal.doubleValue(): 8.0E-7
As you can see, #Ruslan is right. You have to create your own class or use toPlainString() in order to keep the format and not lose any trailing zeros (which should only matter for the human eye, but I even doubt they really do).
In addition, you were right as well when you commented that doubleValue() is not the way to go.
As stated in the only code comment, play around with the precision, maybe calculate some values before printing and/or storing the results in variables.
I have a StreamTokenizer that accepts numbers. However, the parsed number is not the same as the input.
Sample code:
String str = "1000000000000.0000000000000";
double initial = 1000000000000.0000000000000;
InputStream in = new ByteArrayInputStream(str.getBytes());
StreamTokenizer input = new StreamTokenizer(new BufferedReader(new InputStreamReader(in)));
input.parseNumbers();
int n = input.nextToken();
if (n == StreamTokenizer.TT_NUMBER) {
System.out.println("Original: " + str);
System.out.println("Parsed: " + input.nval);
System.out.println(initial + " == " + input.nval + " -> " + (initial == input.nval));
}
Output:
Original: 1000000000000.0000000000000
Parsed: 9.999999999999999E11
1.0E12 == 9.999999999999999E11 -> false
How can this be prevented so the two double values are equal?
EDIT: Linked question discusses why this issue appears. I am asking what are the possible ways to avoid this issue.
An exact way of representing numbers is usage of BigDecimal. Double has a certain precision and working with doubles of various precision (EX: double1=10000.0 and double2=0.0001) could result that the 0.0001 to be dropped. BigDecimal avoids that.
The disadvantages of BigDecimal:
it's slower
operators +, -, *, and / are not overloaded
But if you are dealing with money or having precision is a must, you should use BigDecimal, otherwise you will have losses.
EX:
String str = "1.0E12";
double initial = 1000000000000.0000000000000;
BigDecimal exVal = new BigDecimal(str);
System.out.println("Original: " + str);
System.out.println("Parsed: " + exVal);
System.out.println(initial + " == " + exVal + " -> " + (initial == exVal.doubleValue()));
Program output:
Original: 1.0E12
Parsed: 1.0E+12
1.0E12 == 1.0E+12 -> true
As per David Conrad's analysis, the StreamTokenizer classes handling of numbers with decimal points is flawed, and there doesn't appear to be a work-around.
But this is only one of many short-comings flaws in this class. You would be better off using Scanner or String.split. If the input is really complicated, consider using a parser generator to generate a lexer / parser that precisely implements your input syntax.
Related bugs:
JDK-4638205 : StreamTokenizer: lost precision when parsing long values
JDK-4146533 : java.io.StreamTokenizer: Want to parse scientific numbers
JDK-8180207 : deprecate StringTokenizer and StreamTokenizer
Having said that, applications that use floating point numbers should be tolerant of issues caused by rounding errors and imprecision. There are a number of Q&As on the best way to compare floating point numbers; e.g.
Manipulating and comparing floating points in java
I'm trying in the following code to round a decimal number based on the decimal format that I set at the beginning:
DecimalFormat df = new DecimalFormat("#.000");
df.setRoundingMode(RoundingMode.FLOOR);
double a = Double.parseDouble(df.format(43.473684210526315));
double b = Math.pow(a, 10);
double c = Double.parseDouble(df.format(b));
System.out.println(a + " ** " + b + " ** " + c);
The result that I got is:
43.473 ** 2.4109939006965688E16 ** 2.4109939006965688E16
As you see, the value of a is formatted properly. While the other values are not. After spending a long time trying to understand what is going on, I found out the value 2.4109939006965688E16 can not be formatted. I tested the same value after removing E16 and it worked.
My question is how can I round such a large decimal so that it works as the a?
It's pure luck that a works. If the initial value was 43.4701 you would be seeing 43.47. And in some cases you would see more than 3 decimal places due to the inaccuracy of double.
You only use the DecimalFormatter to create a String briefly before turning back into a double again. You want to keep and use that string.
DecimalFormat df = new DecimalFormat("#.000");
double b = Math.pow(43.473684210526315, 10);
String bFormatted = df.format(b);
System.out.println(bFormatted);
Gives you your desired output 24115485538109308.000
For your "big" decimals you can use the following format:
DecimalFormat df2 = new DecimalFormat("#.000E0");
I see several issues here:
You do not specify a locale for your DecimalFormat. So the combination of DecimalFormat.format and Double.parseDouble is error prone, as e.g. with german locale, DecimalFormat.format will use a comma as decimal separator, which is unsupported by Double.parseDouble, and will throw a NumberFormatException. You should use both format and parse of your DecimalFormat.
Also, you use your double values directly for System.out.println. Why not concatenating the results of DecimalFormat.format, to achieve exactly what you want? E.g. System.out.println(df.format(a) + " ** " + df.format(b) + " ** " + df.format(c));
If you want to do real mathematical rounding (e.g. needing the double value for additional calculations), use Math.round. You can multiply and divide by 10, 100, 1000 etc. to achieve the desired precision. Note that, with the double data type, you can't do exact rounding.
For large numbers, you'll need to use BigInteger or BigDecimal
DecimalFormat df = new DecimalFormat("#.000");
df.setRoundingMode(RoundingMode.FLOOR);
BigDecimal a = new BigDecimal(43.473);
BigDecimal b = a.pow(10);
System.out.println(df.format(a) + " ** " + b.doubleValue() + " ** " + df.format(b));
This results in the following output
43.472 ** 2.4109939006965688E16 ** 24109939006965686.655
I'm using Java but, it's not adding the amount correctly. I'll give my parts of my code.
final double taxrate=.08;
Map<String,Integer> Priceproduct= new HashMap<String,Integer>();
Priceproduct.put("shoes",(int) 50.00);
Priceproduct.put("shirts",(int) 30.00);
Priceproduct.put("shorts",(int) 75.00);
Priceproduct.put("caps",(int) 15.00);
Priceproduct.put("jackets",(int) 100.00);
System.out.print("\n Enter the product: ");
String product=keyboard.nextLine();
System.out.print( "\n Enter the quantity of the product");
int quantity=keyboard.nextInt();
int cost= Priceproduct.get(product)*quantity;
int tax= (int) (cost*taxrate);
System.out.print("\n tax=" +cost*taxrate+"");
int TotalBill= cost+tax;
System.out.print("\nTotal="+cost+ + +tax+"");
When it adds the cost and tax (those two are correct) it's gets the completely wrong answer.
For example 3 shirts= 90, the tax equals 7.2, and the total becomes 907.
Do I need to use DecimalFormat or something else?
Change this:
System.out.print("\nTotal="+cost+ + +tax+"");
to this:
System.out.println();
System.out.print("Total=" + (cost + tax));
(The problem is that + is left-associative, so without parentheses around your addition, "a" + b + c means ("a" + b) + c, which does string-concatenation at both stages.)
When you perform an operation alongside a string Java will perform that operation as if the operands were strings.
In your System.out.println() calls you don't need to redo the calculations, just print out the variables "tax" and "totalBill". (This will solve the problem of printing '907')
You will only ever get integer values because you are using int type for everything. If you want to have decimals to indicate cents you should be using type double.
I want to conver a string to number in Java. I already tried with two methods but both work bad with integers, adding an unneeded floating point: "1" > 1.0 (when I want "1" > 1 and "1.5" > 1.5). I found a couple more ways to convert strings to numbers but they either don't work or are many lines long, I cannot believe it's so complicated coming from javascript where I only need parseFloat().
This is what I'm trying now:
String numString = "1".trim().replaceAll(",","");
float num = (Float.valueOf(numString)).floatValue(); // First try
Double num2 = Double.parseDouble(numString); // Second try
System.out.println(num + " - " + num2); // returns 1.0 - 1.0
How can I have the floating point only when needed?
To format a float as you wish, use DecimalFormat :
DecimalFormat df = new DecimalFormat("#.###");
System.out.println(df.format(1.0f)); // prints 1
System.out.println(df.format(1.5f)); // prints 1.5
In your case, you could use
System.out.println(df.format(num) + " - " + df.format(num2));
I think what you're looking for is DecimalFormat
DecimalFormat format = new DecimalFormat("#.##");
double doubleFromTextField = Double.parseDouble(myField.getText());
System.out.println(format.format(doubleFromTextField));
The problem is with your question really in a type-safe language and I think you are mixing conversion and string representation. In Java or C# or C++ you convert to some predictable/expected type, looks like you expect the "Variant" behavior that you are used to in JavaScript.
What you could do in a type-safe language is this:
public static Object convert(String val)
{
// try to convert to int and if u could then return Integer
ELSE
//try to convert to float and if you could then return it
ELSE
//try to convert to double
etc...
}
Of course this is very inefficient just like JavaScript is compared to C++ or Java. Variants/polymorphism (using Object) comes at cost
Then you could do toString() to get integer formatted as integer, float as float and double as double polymorphically. But your question is ambiguous at best that leads me to believe that there is conceptual problem.