Checking for proper decimal format Java - java

I am creating a budget program in java and need to check to see if the user inputs a valid dollar amount, specifically 2 decimal places. There is no specification on how this should be done.
This is my current attempt but the logic is wrong
aExpense5.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String desc = aExpense3.getText();
String value = aExpense4.getText();
double fValue = 0;
try
{
fValue = Double.valueOf(value);
}
catch (NumberFormatException d)
{
JOptionPane.showMessageDialog(null, "Invalid Number1");
}
double dValue = (fValue * 10) % 10;
if (dValue <= 0)
{
updateExpenseList(desc, fValue);
}
else
{
JOptionPane.showMessageDialog(null,"invalid Number");
}
}
});

You can use regex:
if (value.matches("\\d*\\.\\d\\d")) {
// the number string has two decimal places
}
This regex allows for optional whole number part, ".05" would match.

Try something like:
if (fValue*100 == (int)(fValue*100)) {
//fValue had 2 decimal places or less
}
If fValue = 0.11 then fValue*100 = 11. So you'd have 11 == (int)11 which is true.
If fValue = 0.111 then fValue*100 = 11.1. So you'd have 11.1 == (int)11.1 which is false.

Related

Determine the most fitting numeric variable type for a String

I'm trying to create Predicates to test Strings and determine the most appropriate variable type, which means I want to get the "smallest" numeric variable type that the parsed String fits into.
So for example, for a String "-1.2" the detected type should be float, but if the number exceeds the float range, it should detect double. If the number is even bigger, then BigDecimal.
For non-floating point numbers my tests seem to work fine,
but the decimal numbers are giving me more headaches than they should.
This is my isFloat test:
Predicate<String> isFloat =
s -> {
try {
Double d = Double.parseDouble(s);
return d >= -Float.MAX_VALUE && d <= Float.MAX_VALUE;
} catch (Exception e) {
return false;
}
};
String minOfFloat = String.valueOf(-Float.MAX_VALUE);
System.out.println(minOfFloat);
System.out.println(Double.parseDouble(minOfFloat));
System.out.println(isFloat.test(minOfFloat));
Outputs:
-3.4028235E38
-3.4028235E38
false //WHYYYYY
Similarly my next test would be to check if the number fits a double, and if not, return "BigDecimal".
What's the correct way to test this?
EDIT: This is the way I'm doing it, accepted answer brought me there:
public static final Predicate<String> isFloat =
s -> {
try {
Double d = Double.parseDouble(s);
return d.floatValue() >= -Float.MAX_VALUE
&& d.floatValue() <= Float.MAX_VALUE
&& !Float.isInfinite(d.floatValue())
&& !Float.isNaN(d.floatValue());
} catch (Exception e) {
return false;
}
};
Change your predicate to compare with d.floatValue() >= -Float.MAX_VALUE && d <= Float.MAX_VALUE;
In case, if your double value exceeds float range d.floatValue() returns infinity so you should be good with the change
Predicate<String> isFloat = s -> {
try {
Double d = Double.parseDouble(s);
return d.floatValue() >= -Float.MAX_VALUE && d <= Float.MAX_VALUE;
} catch (Exception e) {
return false;
}
};
String maxDouble = String.valueOf(Double.MAX_VALUE);
System.out.println(maxDouble);
System.out.println(isFloat.test(maxDouble));
Using BigDecimal is recomended when widening primitive conversion will be applied. I couldn't find a good duplicate, but see this posts
how-to-compare-correctly-long-and-float-primitives
comparing-float-and-double-primitives-in-java
to understand why you might get wrong results when comparing two different types. So I would do something like:
Predicate<String> isFloat =
str -> new BigDecimal(str).compareTo(new BigDecimal(String.valueOf(Float.MAX_VALUE))) <= 0 &&
new BigDecimal(str).compareTo(new BigDecimal(String.valueOf(-Float.MAX_VALUE))) >= 0;

Java FX arithmetic expression in a button

hi i want to do a button that takes two input fields and trying to do the following :
chick if it's a number .(so it can devide the two numbers)
i can't devide any number by zero .
and showing that it's a arithmetic expression .
so any help ?
the code is blow ::
enter image description here
code ::
b4.setOnMouseClicked((MouseEvent ex) -> {
String Num1 = tf4.getText();
String Num2 = tf8.getText();
if(Num1.matches("^\\d+(\\.\\d+)?") && Num2.matches("^\\d+(\\.\\d+)?")) {
try {
double Num1f = Double.parseDouble(Num1);
double Num2f = Double.parseDouble(Num2);
double result =(Num2f / Num1f);
valf4.setText(String.valueOf(result));
}
catch (ArithmeticException e) {
System.out.println("ArithmeticException");
valf4.setText("You can't do that !");
}
} else {
}
});
and it show infinity
not what i expected as i did in catch area
Floating point arithmetic in Java does not throw exceptions for division by zero; it evaluates to one of the special values in the Double class (Double.POSITIVE_INFINITY or Double.NEGATIVE_INFINITY).
Instead of catching the exception, you can just test if the denominator is zero, or test if the result is infinite:
b4.setOnMouseClicked((MouseEvent ex) -> {
String num1 = tf4.getText();
String num2 = tf8.getText();
if(num1.matches("^\\d+(\\.\\d+)?") && num2.matches("^\\d+(\\.\\d+)?")) {
double num1f = Double.parseDouble(num1);
double num2f = Double.parseDouble(num2);
double result = num2f / num1f;
if (Double.isInfinite(result)) {
valf4.setText("You can't do that !");
} else {
valf4.setText(String.valueOf(result));
}
} else {
}
});

Showing 0 after decimal separator in java

i'm doing a calculator app and i'm using Decimal Format to format my number.
My problem is i want it to show number like 0,003. But 2 zero after the comma didn't show up until I typing 3. Please help me fix this
Here my code
DecimalFormatSymbols formatSymbolsGermany = DecimalFormatSymbols.getInstance(Locale.GERMANY);
DecimalFormat decimalFormat = new DecimalFormat("#,###,###.########", formatSymbolsGermany);
My code to add "0"
private void zeroOnClick() {
if (tvNumber.getText().toString().length() < 11) {
convertNumber("0");
}
}
private void convertNumber(String number) {
number1 += number;
try {
double a = Double.parseDouble(number1.replace(',', '.'));
tvNumber.setText(decimalFormat.format(a));
delete = true;
} catch (Exception e) {
e.printStackTrace();
}
}
private void addComma(){
if (comma) {
//do nothing
} else {
number1 += ",";
tvNumber.setText(number1);
comma = true;
}
}
The simplest solution would be to just tvNumber.setText(number1); directly without the back-and-forth conversion while editing and display it in the proper format only after the editing is done.
Another possibility would be to artificially append a digit before the conversion if the number contains a decimal point and then remove it afterwards.
String res = number1.replace(',', '.'); // shouldn't this be decimalFormat dependent ?
if( number1.contains(".") ) {
res = decimalFormat.format( Double.parseDouble(res+"5"));
res = res.substring(0,res.length()-1);
} else {
res = decimalFormat.format( Double.parseDouble(res) );
}

How to get rid of .0 on end of whole float number [duplicate]

A 64-bit double can represent integer +/- 253 exactly.
Given this fact, I choose to use a double type as a single type for all my types, since my largest integer is an unsigned 32-bit number.
But now I have to print these pseudo integers, but the problem is they are also mixed in with actual doubles.
So how do I print these doubles nicely in Java?
I have tried String.format("%f", value), which is close, except I get a lot of trailing zeros for small values.
Here's an example output of of %f
232.00000000
0.18000000000
1237875192.0
4.5800000000
0.00000000
1.23450000
What I want is:
232
0.18
1237875192
4.58
0
1.2345
Sure I can write a function to trim those zeros, but that's lot of performance loss due to string manipulation. Can I do better with other format code?
The answers by Tom E. and Jeremy S. are unacceptable as they both arbitrarily rounds to two decimal places. Please understand the problem before answering.
Please note that String.format(format, args...) is locale-dependent (see answers below).
If the idea is to print integers stored as doubles as if they are integers, and otherwise print the doubles with the minimum necessary precision:
public static String fmt(double d)
{
if(d == (long) d)
return String.format("%d",(long)d);
else
return String.format("%s",d);
}
Produces:
232
0.18
1237875192
4.58
0
1.2345
And does not rely on string manipulation.
String.format("%.2f", value);
In short:
If you want to get rid of trailing zeros and locale problems, then you should use:
double myValue = 0.00000021d;
DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(340); //340 = DecimalFormat.DOUBLE_FRACTION_DIGITS
System.out.println(df.format(myValue)); //output: 0.00000021
Explanation:
Why other answers did not suit me:
Double.toString() or System.out.println or FloatingDecimal.toJavaFormatString uses scientific notations if double is less than 10^-3 or greater than or equal to 10^7
double myValue = 0.00000021d;
String.format("%s", myvalue); //output: 2.1E-7
by using %f, the default decimal precision is 6, otherwise you can hardcode it, but it results in extra zeros added if you have fewer decimals. Example:
double myValue = 0.00000021d;
String.format("%.12f", myvalue); // Output: 0.000000210000
by using setMaximumFractionDigits(0); or %.0f you remove any decimal precision, which is fine for integers/longs but not for double
double myValue = 0.00000021d;
System.out.println(String.format("%.0f", myvalue)); // Output: 0
DecimalFormat df = new DecimalFormat("0");
System.out.println(df.format(myValue)); // Output: 0
by using DecimalFormat, you are local dependent. In the French locale, the decimal separator is a comma, not a point:
double myValue = 0.00000021d;
DecimalFormat df = new DecimalFormat("0");
df.setMaximumFractionDigits(340);
System.out.println(df.format(myvalue)); // Output: 0,00000021
Using the ENGLISH locale makes sure you get a point for decimal separator, wherever your program will run.
Why using 340 then for setMaximumFractionDigits?
Two reasons:
setMaximumFractionDigits accepts an integer, but its implementation has a maximum digits allowed of DecimalFormat.DOUBLE_FRACTION_DIGITS which equals 340
Double.MIN_VALUE = 4.9E-324 so with 340 digits you are sure not to round your double and lose precision
Use:
if (d % 1.0 != 0)
return String.format("%s", d);
else
return String.format("%.0f", d);
This should work with the extreme values supported by Double. It yields:
0.12
12
12.144252
0
On my machine, the following function is roughly 7 times faster than the function provided by JasonD's answer, since it avoids String.format:
public static String prettyPrint(double d) {
int i = (int) d;
return d == i ? String.valueOf(i) : String.valueOf(d);
}
My two cents:
if(n % 1 == 0) {
return String.format(Locale.US, "%.0f", n));
} else {
return String.format(Locale.US, "%.1f", n));
}
if (d == Math.floor(d)) {
return String.format("%.0f", d); //Format is: 0 places after decimal point
} else {
return Double.toString(d);
}
More info: https://docs.oracle.com/javase/tutorial/java/data/numberformat.html
float price = 4.30;
DecimalFormat format = new DecimalFormat("0.##"); // Choose the number of decimal places to work with in case they are different than zero and zero value will be removed
format.setRoundingMode(RoundingMode.DOWN); // Choose your Rounding Mode
System.out.println(format.format(price));
This is the result of some tests:
4.30 => 4.3
4.39 => 4.39 // Choose format.setRoundingMode(RoundingMode.UP) to get 4.4
4.000000 => 4
4 => 4
Naw, never mind. The performance loss due to string manipulation is zero.
And here's the code to trim the end after %f:
private static String trimTrailingZeros(String number) {
if(!number.contains(".")) {
return number;
}
return number.replaceAll("\\.?0*$", "");
}
Use a DecimalFormat and setMinimumFractionDigits(0).
This one will gets the job done nicely:
public static String removeZero(double number) {
DecimalFormat format = new DecimalFormat("#.###########");
return format.format(number);
}
new DecimalFormat("00.#").format(20.236)
//out =20.2
new DecimalFormat("00.#").format(2.236)
//out =02.2
0 for minimum number of digits
Renders # digits
Please note that String.format(format, args...) is locale-dependent because it formats using the user's default locale, that is, probably with commas and even spaces inside like 123 456,789 or 123,456.789, which may be not exactly what you expect.
You may prefer to use String.format((Locale)null, format, args...).
For example,
double f = 123456.789d;
System.out.println(String.format(Locale.FRANCE,"%f",f));
System.out.println(String.format(Locale.GERMANY,"%f",f));
System.out.println(String.format(Locale.US,"%f",f));
prints
123456,789000
123456,789000
123456.789000
and this is what will String.format(format, args...) do in different countries.
EDIT Ok, since there has been a discussion about formalities:
res += stripFpZeroes(String.format((Locale) null, (nDigits!=0 ? "%."+nDigits+"f" : "%f"), value));
...
protected static String stripFpZeroes(String fpnumber) {
int n = fpnumber.indexOf('.');
if (n == -1) {
return fpnumber;
}
if (n < 2) {
n = 2;
}
String s = fpnumber;
while (s.length() > n && s.endsWith("0")) {
s = s.substring(0, s.length()-1);
}
return s;
}
I made a DoubleFormatter to efficiently convert a great numbers of double values to a nice/presentable string:
double horribleNumber = 3598945.141658554548844;
DoubleFormatter df = new DoubleFormatter(4, 6); // 4 = MaxInteger, 6 = MaxDecimal
String beautyDisplay = df.format(horribleNumber);
If the integer part of V has more than MaxInteger => display V in scientific format (1.2345E+30). Otherwise, display in normal format (124.45678).
the MaxDecimal decide numbers of decimal digits (trim with bankers' rounding)
Here the code:
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
/**
* Convert a double to a beautiful String (US-local):
*
* double horribleNumber = 3598945.141658554548844;
* DoubleFormatter df = new DoubleFormatter(4,6);
* String beautyDisplay = df.format(horribleNumber);
* String beautyLabel = df.formatHtml(horribleNumber);
*
* Manipulate 3 instances of NumberFormat to efficiently format a great number of double values.
* (avoid to create an object NumberFormat each call of format()).
*
* 3 instances of NumberFormat will be reused to format a value v:
*
* if v < EXP_DOWN, uses nfBelow
* if EXP_DOWN <= v <= EXP_UP, uses nfNormal
* if EXP_UP < v, uses nfAbove
*
* nfBelow, nfNormal and nfAbove will be generated base on the precision_ parameter.
*
* #author: DUONG Phu-Hiep
*/
public class DoubleFormatter
{
private static final double EXP_DOWN = 1.e-3;
private double EXP_UP; // always = 10^maxInteger
private int maxInteger_;
private int maxFraction_;
private NumberFormat nfBelow_;
private NumberFormat nfNormal_;
private NumberFormat nfAbove_;
private enum NumberFormatKind {Below, Normal, Above}
public DoubleFormatter(int maxInteger, int maxFraction){
setPrecision(maxInteger, maxFraction);
}
public void setPrecision(int maxInteger, int maxFraction){
Preconditions.checkArgument(maxFraction>=0);
Preconditions.checkArgument(maxInteger>0 && maxInteger<17);
if (maxFraction == maxFraction_ && maxInteger_ == maxInteger) {
return;
}
maxFraction_ = maxFraction;
maxInteger_ = maxInteger;
EXP_UP = Math.pow(10, maxInteger);
nfBelow_ = createNumberFormat(NumberFormatKind.Below);
nfNormal_ = createNumberFormat(NumberFormatKind.Normal);
nfAbove_ = createNumberFormat(NumberFormatKind.Above);
}
private NumberFormat createNumberFormat(NumberFormatKind kind) {
// If you do not use the Guava library, replace it with createSharp(precision);
final String sharpByPrecision = Strings.repeat("#", maxFraction_);
NumberFormat f = NumberFormat.getInstance(Locale.US);
// Apply bankers' rounding: this is the rounding mode that
// statistically minimizes cumulative error when applied
// repeatedly over a sequence of calculations
f.setRoundingMode(RoundingMode.HALF_EVEN);
if (f instanceof DecimalFormat) {
DecimalFormat df = (DecimalFormat) f;
DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();
// Set group separator to space instead of comma
//dfs.setGroupingSeparator(' ');
// Set Exponent symbol to minus 'e' instead of 'E'
if (kind == NumberFormatKind.Above) {
dfs.setExponentSeparator("e+"); //force to display the positive sign in the exponent part
} else {
dfs.setExponentSeparator("e");
}
df.setDecimalFormatSymbols(dfs);
// Use exponent format if v is outside of [EXP_DOWN,EXP_UP]
if (kind == NumberFormatKind.Normal) {
if (maxFraction_ == 0) {
df.applyPattern("#,##0");
} else {
df.applyPattern("#,##0."+sharpByPrecision);
}
} else {
if (maxFraction_ == 0) {
df.applyPattern("0E0");
} else {
df.applyPattern("0."+sharpByPrecision+"E0");
}
}
}
return f;
}
public String format(double v) {
if (Double.isNaN(v)) {
return "-";
}
if (v==0) {
return "0";
}
final double absv = Math.abs(v);
if (absv<EXP_DOWN) {
return nfBelow_.format(v);
}
if (absv>EXP_UP) {
return nfAbove_.format(v);
}
return nfNormal_.format(v);
}
/**
* Format and higlight the important part (integer part & exponent part)
*/
public String formatHtml(double v) {
if (Double.isNaN(v)) {
return "-";
}
return htmlize(format(v));
}
/**
* This is the base alogrithm: create a instance of NumberFormat for the value, then format it. It should
* not be used to format a great numbers of value
*
* We will never use this methode, it is here only to understanding the Algo principal:
*
* format v to string. precision_ is numbers of digits after decimal.
* if EXP_DOWN <= abs(v) <= EXP_UP, display the normal format: 124.45678
* otherwise display scientist format with: 1.2345e+30
*
* pre-condition: precision >= 1
*/
#Deprecated
public String formatInefficient(double v) {
// If you do not use Guava library, replace with createSharp(precision);
final String sharpByPrecision = Strings.repeat("#", maxFraction_);
final double absv = Math.abs(v);
NumberFormat f = NumberFormat.getInstance(Locale.US);
// Apply bankers' rounding: this is the rounding mode that
// statistically minimizes cumulative error when applied
// repeatedly over a sequence of calculations
f.setRoundingMode(RoundingMode.HALF_EVEN);
if (f instanceof DecimalFormat) {
DecimalFormat df = (DecimalFormat) f;
DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();
// Set group separator to space instead of comma
dfs.setGroupingSeparator(' ');
// Set Exponent symbol to minus 'e' instead of 'E'
if (absv>EXP_UP) {
dfs.setExponentSeparator("e+"); //force to display the positive sign in the exponent part
} else {
dfs.setExponentSeparator("e");
}
df.setDecimalFormatSymbols(dfs);
//use exponent format if v is out side of [EXP_DOWN,EXP_UP]
if (absv<EXP_DOWN || absv>EXP_UP) {
df.applyPattern("0."+sharpByPrecision+"E0");
} else {
df.applyPattern("#,##0."+sharpByPrecision);
}
}
return f.format(v);
}
/**
* Convert "3.1416e+12" to "<b>3</b>.1416e<b>+12</b>"
* It is a html format of a number which highlight the integer and exponent part
*/
private static String htmlize(String s) {
StringBuilder resu = new StringBuilder("<b>");
int p1 = s.indexOf('.');
if (p1>0) {
resu.append(s.substring(0, p1));
resu.append("</b>");
} else {
p1 = 0;
}
int p2 = s.lastIndexOf('e');
if (p2>0) {
resu.append(s.substring(p1, p2));
resu.append("<b>");
resu.append(s.substring(p2, s.length()));
resu.append("</b>");
} else {
resu.append(s.substring(p1, s.length()));
if (p1==0){
resu.append("</b>");
}
}
return resu.toString();
}
}
Note: I used two functions from the Guava library. If you don't use Guava, code it yourself:
/**
* Equivalent to Strings.repeat("#", n) of the Guava library:
*/
private static String createSharp(int n) {
StringBuilder sb = new StringBuilder();
for (int i=0; i<n; i++) {
sb.append('#');
}
return sb.toString();
}
String s = String.valueof("your int variable");
while (g.endsWith("0") && g.contains(".")) {
g = g.substring(0, g.length() - 1);
if (g.endsWith("."))
{
g = g.substring(0, g.length() - 1);
}
}
You said you choose to store your numbers with the double type. I think this could be the root of the problem, because it forces you to store integers into doubles (and therefore losing the initial information about the value's nature). What about storing your numbers in instances of the Number class (superclass of both Double and Integer) and rely on polymorphism to determine the correct format of each number?
I know it may not be acceptable to refactor a whole part of your code due to that, but it could produce the desired output without extra code/casting/parsing.
Example:
import java.util.ArrayList;
import java.util.List;
public class UseMixedNumbers {
public static void main(String[] args) {
List<Number> listNumbers = new ArrayList<Number>();
listNumbers.add(232);
listNumbers.add(0.18);
listNumbers.add(1237875192);
listNumbers.add(4.58);
listNumbers.add(0);
listNumbers.add(1.2345);
for (Number number : listNumbers) {
System.out.println(number);
}
}
}
Will produce the following output:
232
0.18
1237875192
4.58
0
1.2345
For Kotlin you can use an extension like:
fun Double.toPrettyString() =
if(this - this.toLong() == 0.0)
String.format("%d", this.toLong())
else
String.format("%s", this)
This is what I came up with:
private static String format(final double dbl) {
return dbl % 1 != 0 ? String.valueOf(dbl) : String.valueOf((int) dbl);
}
It is a simple one-liner and only casts to int if it really needs to.
Format price with grouping, rounding, and no unnecessary zeroes (in double).
Rules:
No zeroes at the end (2.0000 = 2; 1.0100000 = 1.01)
Two digits maximum after a point (2.010 = 2.01; 0.20 = 0.2)
Rounding after the 2nd digit after a point (1.994 = 1.99; 1.995 = 2; 1.006 = 1.01; 0.0006 -> 0)
Returns 0 (null/-0 = 0)
Adds $ (= $56/-$56)
Grouping (101101.02 = $101,101.02)
More examples:
-99.985 = -$99.99
10 = $10
10.00 = $10
20.01000089 = $20.01
It is written in Kotlin as a fun extension of Double (because it is used in Android), but it can be converted to Java easily, because Java classes were used.
/**
* 23.0 -> $23
*
* 23.1 -> $23.1
*
* 23.01 -> $23.01
*
* 23.99 -> $23.99
*
* 23.999 -> $24
*
* -0.0 -> $0
*
* -5.00 -> -$5
*
* -5.019 -> -$5.02
*/
fun Double?.formatUserAsSum(): String {
return when {
this == null || this == 0.0 -> "$0"
this % 1 == 0.0 -> DecimalFormat("$#,##0;-$#,##0").format(this)
else -> DecimalFormat("$#,##0.##;-$#,##0.##").format(this)
}
}
How to use:
var yourDouble: Double? = -20.00
println(yourDouble.formatUserAsSum()) // will print -$20
yourDouble = null
println(yourDouble.formatUserAsSum()) // will print $0
About DecimalFormat: https://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html
A simple solution with locale in mind:
double d = 123.45;
NumberFormat numberFormat = NumberFormat.getInstance(Locale.GERMANY);
System.out.println(numberFormat.format(d));
Since comma is used as decimal separator in Germany, the above will print:
123,45
Here's another answer that has an option to append decimal ONLY IF decimal was not zero.
/**
* Example: (isDecimalRequired = true)
* d = 12345
* returns 12,345.00
*
* d = 12345.12345
* returns 12,345.12
*
* ==================================================
* Example: (isDecimalRequired = false)
* d = 12345
* returns 12,345 (notice that there's no decimal since it's zero)
*
* d = 12345.12345
* returns 12,345.12
*
* #param d float to format
* #param zeroCount number decimal places
* #param isDecimalRequired true if it will put decimal even zero,
* false will remove the last decimal(s) if zero.
*/
fun formatDecimal(d: Float? = 0f, zeroCount: Int, isDecimalRequired: Boolean = true): String {
val zeros = StringBuilder()
for (i in 0 until zeroCount) {
zeros.append("0")
}
var pattern = "#,##0"
if (zeros.isNotEmpty()) {
pattern += ".$zeros"
}
val numberFormat = DecimalFormat(pattern)
var formattedNumber = if (d != null) numberFormat.format(d) else "0"
if (!isDecimalRequired) {
for (i in formattedNumber.length downTo formattedNumber.length - zeroCount) {
val number = formattedNumber[i - 1]
if (number == '0' || number == '.') {
formattedNumber = formattedNumber.substring(0, formattedNumber.length - 1)
} else {
break
}
}
}
return formattedNumber
}
Here are two ways to achieve it. First, the shorter (and probably better) way:
public static String formatFloatToString(final float f)
{
final int i = (int)f;
if(f == i)
return Integer.toString(i);
return Float.toString(f);
}
And here's the longer and probably worse way:
public static String formatFloatToString(final float f)
{
final String s = Float.toString(f);
int dotPos = -1;
for(int i=0; i<s.length(); ++i)
if(s.charAt(i) == '.')
{
dotPos = i;
break;
}
if(dotPos == -1)
return s;
int end = dotPos;
for(int i = dotPos + 1; i<s.length(); ++i)
{
final char c = s.charAt(i);
if(c != '0')
end = i + 1;
}
final String result = s.substring(0, end);
return result;
}
public static String fmt(double d) {
String val = Double.toString(d);
String[] valArray = val.split("\\.");
long valLong = 0;
if(valArray.length == 2) {
valLong = Long.parseLong(valArray[1]);
}
if (valLong == 0)
return String.format("%d", (long) d);
else
return String.format("%s", d);
}
I had to use this because d == (long)d was giving me violation in a SonarQube report.
I am using this for formatting numbers without trailing zeroes in our JSF application. The original built-in formatters required you to specify max numbers of fractional digits which could be useful here also in case you have too many fractional digits.
/**
* Formats the given Number as with as many fractional digits as precision
* available.<br>
* This is a convenient method in case all fractional digits shall be
* rendered and no custom format / pattern needs to be provided.<br>
* <br>
* This serves as a workaround for {#link NumberFormat#getNumberInstance()}
* which by default only renders up to three fractional digits.
*
* #param number
* #param locale
* #param groupingUsed <code>true</code> if grouping shall be used
*
* #return
*/
public static String formatNumberFraction(final Number number, final Locale locale, final boolean groupingUsed)
{
if (number == null)
return null;
final BigDecimal bDNumber = MathUtils.getBigDecimal(number);
final NumberFormat numberFormat = NumberFormat.getNumberInstance(locale);
numberFormat.setMaximumFractionDigits(Math.max(0, bDNumber.scale()));
numberFormat.setGroupingUsed(groupingUsed);
// Convert back for locale percent formatter
return numberFormat.format(bDNumber);
}
/**
* Formats the given Number as percent with as many fractional digits as
* precision available.<br>
* This is a convenient method in case all fractional digits shall be
* rendered and no custom format / pattern needs to be provided.<br>
* <br>
* This serves as a workaround for {#link NumberFormat#getPercentInstance()}
* which does not renders fractional digits.
*
* #param number Number in range of [0-1]
* #param locale
*
* #return
*/
public static String formatPercentFraction(final Number number, final Locale locale)
{
if (number == null)
return null;
final BigDecimal bDNumber = MathUtils.getBigDecimal(number).multiply(new BigDecimal(100));
final NumberFormat percentScaleFormat = NumberFormat.getPercentInstance(locale);
percentScaleFormat.setMaximumFractionDigits(Math.max(0, bDNumber.scale() - 2));
final BigDecimal bDNumberPercent = bDNumber.multiply(new BigDecimal(0.01));
// Convert back for locale percent formatter
final String strPercent = percentScaleFormat.format(bDNumberPercent);
return strPercent;
}
work with given decimal length...
public static String getLocaleFloatValueDecimalWithLength(Locale loc, float value, int length) {
//make string from float value
return String.format(loc, (value % 1 == 0 ? "%.0f" : "%."+length+"f"), value);
}
0.0 -> 0%
1.0 -> 100%
0.1 -> 10%
0.11 -> 11%
0.01 -> 1%
0.111 -> 11.1%
0.001 -> 0.1%
0.1111 -> 11.11%
0.0001 -> 0.01%
".replace()" is added because I was always getting wrong separator
import java.text.NumberFormat
fun Double.formating(): String {
val defaultFormat: NumberFormat = NumberFormat.getPercentInstance()
defaultFormat.minimumFractionDigits = 0
defaultFormat.maximumFractionDigits = 2
return defaultFormat.format(this).replace(",", ".")
}
Here is an answer that actually works (combination of different answers here)
public static String removeTrailingZeros(double f)
{
if(f == (int)f) {
return String.format("%d", (int)f);
}
return String.format("%f", f).replaceAll("0*$", "");
}
The best way to do this is as below:
public class Test {
public static void main(String args[]){
System.out.println(String.format("%s something", new Double(3.456)));
System.out.println(String.format("%s something", new Double(3.456234523452)));
System.out.println(String.format("%s something", new Double(3.45)));
System.out.println(String.format("%s something", new Double(3)));
}
}
Output:
3.456 something
3.456234523452 something
3.45 something
3.0 something
The only issue is the last one where .0 doesn't get removed. But if you are able to live with that then this works best. %.2f will round it to the last two decimal digits. So will DecimalFormat. If you need all the decimal places, but not the trailing zeros then this works best.
String s = "1.210000";
while (s.endsWith("0")){
s = (s.substring(0, s.length() - 1));
}
This will make the string to drop the tailing 0-s.

how to compare a Double Value in if statement in java?

I have a desktop application with textboxs that contain a price values. As an example if i input 25000
Double priceSec = Double.parseDouble(cusPrice.getText());
i'm passing that 25000 as a double value
so now i want to compare that value and check whether it is empty or not?
if(cusPrice2.getText()==null || cusPrice2.getText().isEmpty()){
Double priceSec=0.0;
}
i know i can create an else condition for
if textbox !=null
total=txtbox1+txtbox2+txtbox3;
if textbox value is empty or not empty. value should be there in total.
but in my code ,it displays as null.
Do i have any other way to do that?
can you tell me a way to do that.
here is my full code
private void cusOkBtnActionPerformed(java.awt.event.ActionEvent evt) {
Double priceSec = Double.parseDouble(cusPrice2.getText());
Double priceThird = Double.parseDouble(cusPrice3.getText());
Double priceFourth = Double.parseDouble(cusPrice4.getText());
Double priceFifth = Double.parseDouble(cusPrice5.getText());
if(cusPrice2.getText()==null || cusPrice2.getText().isEmpty() || cusPrice2.getText() !=null ){
priceSec=0.0;
costCls.setItemPrice(priceSec);
}
else if(cusPrice3.getText()==null || cusPrice3.getText().isEmpty()){
priceThird=0.0;
}
else if(cusPrice4.getText()==null || cusPrice4.getText().isEmpty()){
priceFourth=0.0;
}
else if(cusPrice5.getText()==null || cusPrice5.getText().isEmpty()){
priceFifth=0.0;
}
Double setItemTotal = priceCus+priceSec+priceThird+priceFourth+priceFifth;
}
You should rather use Exceptions.
try {
Double priceSec = Double.parseDouble(cusPrice.getText());
} catch (NullPointerException e1) {
//null somewhere
} catch (NumberFormatException e2) {
//not a number - on controlled input - empty field.
}
double is the primitive type for floating point, Double is the Object child that wraps a double value. So:
double priceSec = Double.parseDouble(cusPrice.getText());
double price2Sec = cusPrice2.getText().isEmpty())
? 0.0
: Double.parseDouble(cusPrice.getText());
if (priceSec == price2Sec) { ...
However for financial data a double has small approximation errors, that can become visible - especially with ==. Hence one might better use BigDecimal, which does fixed point arithmetic.
BigDecimal priceSec = new BigDecimal(cusPrice.getText());
if (priceSec.compareTo(price2Sec) == 0) { ...
With a bit ugly API doing calculations:
x = x.add(y.divide(new BigDecimal("12.50")));
you can try this
private void cusOkBtnActionPerformed(java.awt.event.ActionEvent evt) {
Double priceSec=0.0,priceThird=0.0,priceFourth=0.0,priceFifth=0.0;
costCls.setItemPrice(0.0);
if(cusPrice2.getText()!=null && !cusPrice2.getText().isEmpty() ){
priceSec = Double.parseDouble(cusPrice2.getText());
costCls.setItemPrice(priceSec);
}
else if(cusPrice3.getText()!=null && !cusPrice3.getText().isEmpty()){
priceThird = Double.parseDouble(cusPrice3.getText());
}
else if(cusPrice4.getText()!=null && !cusPrice4.getText().isEmpty()){
priceFourth = Double.parseDouble(cusPrice4.getText());
}
else if(cusPrice5.getText()!=null && !cusPrice5.getText().isEmpty()){
priceFifth = Double.parseDouble(cusPrice5.getText());
}
Double setItemTotal = priceCus+priceSec+priceThird+priceFourth+priceFifth;
}
It is better to use the built-in Exception semantics already available within the Double.parseDouble(String s) implementation. (IMHO: Don't check up-front as you are making the exceptional-situation part of the normal flow)
Use a function like
private static double getValue(String str) {
try {
return Double.parseDouble(str);
} catch (NumberFormatException e) {
return 0d;
}
}
You would then use it like:
String priceStr = cusPrice.getText();
double d = getValue(priceStr);

Categories

Resources