what is the best way to handle double value while split? - java

String x = "39.33";
String result ;
Double x1 = new Double(x);
System.err.println("value :"+ x1);
String[] parts = x1.toString().split("\\.");
if(parts != null )
{
if((Integer.parseInt(parts[1])) > 0)
{
result =x1;
}
else
{
result= parts[0];
}
}
please let me know the best way to format/split the value:
my need is....
if x is 39
so x1 is 39.0
so i need result =39
if x is 39.33
so x1 is 39.33
so i need result =39.33
i dont want to use split or condition checking if((Integer.parseInt(parts[1])) > 0).. please let me know the best way for this?

Try this:
Double d = Double.parseDouble("35.0");
String result = NumberFormat.getNumberInstance().format(d.doubleValue())
System.out.println(result);

if you convert your double to an int the decimal places are ignored.
for this problem it would be something like that:
String result;
String x = "39.33";
Double x1 = new Double(x);
int xPre = x1.intValue();
if ( x1 > xPre) {
result = x1;
} else {
result = Integer.toString(xPre);
}

All you need to do is to read the number as a double and cast it to an int, which will effectively truncate the number.

You can do
String x = "39.33";
long l = (long) Double.parseDouble(x); // == 39
This will result in l being the whole number part of the double. (provided the number is less than 9 billion billion)
If you really want to use split you can do the following which will be slightly slower but will throw an exception if the number is too large.
long l = Long.parseLong(x.split("\\.")[0]);

public static void main(String[] args) {
Double x = new Double("39.33");
Double y = new Double("39.0");
printDouble(x);
printDouble(y);
}
public static void printDouble(Double dbl){
System.out.println(dbl.toString().replaceAll("[0]*$", "").replaceAll(".$", ""));
}

Related

Round Double datatype upto 3 digits

I am trying to calculate the value a field which represent Interest rate for that I have to round up the value to 3 digits.
Below is code which I am using :
double bigAmt1 = Double.parseDouble(amount);
bigAmt = (intsign*bigAmt1)/div;
bigAmt=Math.round(bigAmt*1000d)/1000d;
amount = 4048500
intsign = 1
div = 6
it returns = 4.048
I need it return = 4.049
if I change the value of amount to 4048600 then it return 4.049 so I think it is rounding up values where last digit after division is greater than 5 but It should be if last digit equal or greater than 5 then It should round up to next digit.
Below is my test class --
package test;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(divideAndConvertToString1("4048100","6","1"));
//System.out.println("---> 3 places "+Math.round(3.5));
//Math.round(3.7)
/*double value = 12.3457652133;
value =Double.parseDouble(new DecimalFormat("##.####").format(value));
System.out.println("---> 3 places "+value);*/
}
public static String divideAndConvertToString(String amount, String decml, String sign) {
double bigAmt = 0.00;
int div = 0;
double d =0;
if (!isStringEmpty(decml)) {
d = Double.parseDouble(decml);
}
double d1 = Math.pow(10, d);
div = (int)d1;
int intsign = Integer.parseInt(sign);
if (amount != null && !"".equalsIgnoreCase(amount)) {
//BigDecimal bigAmt1 = new BigDecimal(amount);
double bigAmt1 = Double.parseDouble(amount);
bigAmt = (intsign*bigAmt1)/div;
bigAmt=Math.ceil(bigAmt*1000d)/1000d;
//bigAmt = new BigDecimal((intsign*bigAmt1.doubleValue())/div);
return String.valueOf(bigAmt);
}
else {
bigAmt = bigAmt;
}
System.out.println("inside divideAndConvertToString");
return String.valueOf(bigAmt);
}
public static String divideAndConvertToString1(String amount, String decml, String sign) {
BigDecimal bigAmt = null;
int div = 0;
double d =0;
if (!Util.isStringEmpty(decml)) {
d = Double.parseDouble(decml);
}
double d1 = Math.pow(10, d);
div = (int)d1;
int intsign = Integer.parseInt(sign);
if (amount != null && !"".equalsIgnoreCase(amount)) {
BigDecimal bigAmt1 = new BigDecimal(amount);
bigAmt = new BigDecimal((intsign*bigAmt1.doubleValue())/div);
}
else {
bigAmt = new BigDecimal("0");
}
System.out.println("inside divideAndConvertToString1");
return String.valueOf(bigAmt.setScale(3, RoundingMode.CEILING));
//System.out.println(b.setScale(0, RoundingMode.CEILING));
}
public static boolean isStringEmpty(String input) {
if (input == null || input.trim().length() == 0 || "".equalsIgnoreCase(input)) {
return true;
}
return false;
}
}
Math.round should work however I usual do this like this:
bigAmt=Math.floor((bigAmt*1000d)+0.5d)/1000d;
Your problem however lies elsewhere:
bigAmt1 = Double.parseDouble(amount);
bigAmt = (intsign*bigAmt1)/div;
bigAmt=Math.round(bigAmt*1000d)/1000d;
So using your values:
amount = 4048500
intsign = 1
div = 6
bigAmt1 = 4048500;
bigAmt = (1*4048500)/6 = 674750;
bigAmt= round(674750*1000)/1000 = round(674750000)/1000 = 674750;
However in your example You wrote: it returns = 4.048 I need it return = 4.049 So do you have the same div value?
If the div is 1000000 instead then:
bigAmt1 = 4048500;
bigAmt = (1*4048500)/1000000 = 4.048500;
bigAmt= round(4.048500*1000)/1000 = round(4048.500)/1000 = 4.049;
However there is a big problem because floating point might round your 4.048500 number to something like 4.048499999999. It is safer to use integer rounding directly:
1000* ((amount+500)/1000)
1000* ((4048500+500)/1000)
1000* ((4049000 )/1000)
1000* (4049)
4049000
So you add half of the rounding value, divide by rounding value and then multiply by rounding value. All done on integers
Why won't you use Math.ceil(), instead of Math.round(), I think that's what it's for.

Extracting digit values from before and after decimal points in Java

I have 2 values
String latitude = "37.348541";
String longitude = "-121.88627";
I would like to extract like the values as below with out any rounding up the values.
latitude = "37.34";
longitude = "-121.88";
I tried using DecimalFormat.format, but it does some round up and I want to extract an exact value.
You can define a function using String#substring and String#indexOf as shown below:
public class Main {
public static void main(String[] args) {
// Tests
System.out.println(getNumberUptoTwoDecimalPlaces("37.348541"));
System.out.println(getNumberUptoTwoDecimalPlaces("-121.88627"));
System.out.println(getNumberUptoTwoDecimalPlaces("-121.8"));
System.out.println(getNumberUptoTwoDecimalPlaces("-121.88"));
System.out.println(getNumberUptoTwoDecimalPlaces("-121.889"));
}
static String getNumberUptoTwoDecimalPlaces(String number) {
int indexOfPoint = number.indexOf('.');
if (indexOfPoint != -1 && number.length() >= indexOfPoint + 3) {
return number.substring(0, indexOfPoint + 3);
} else {
return number;
}
}
}
Output:
37.34
-121.88
-121.8
-121.88
-121.88
For example:
String latitude = "37.348541";
int i = latitude.indexOf(".");
if(i > 0 && i < latitude.length()-2) latitude = latitude.substring(i, i+2);
You can use the BigDecimal class and the ROUND_DOWN option. So the code could look like this:
BigDecimal number = new BigDecimal("123.13298");
BigDecimal roundedNumber = number.setScale(2, BigDecimal.ROUND_DOWN);
System.out.println(roundedNumber);
Otherwise you can also use the native double and the Math.floor or the Math.ceil method:
double number = 123.13598;
double roundedNumber = (number < 0 ? Math.ceil(number * 100) : Math.floor(number * 100)) / 100;
System.out.println(roundedNumber);

how to get decimal values as a new interger and traverse that integer from left to right?

I have a business case where I need to get the decimal values as a new integer and
then traverse it from left to right to evaluate.
Eg: I have a integer value int val=1345679;
square root of val is double sqrt_val=1160.03405122; //sqrt(1345679), decimal values are limit to 8 digits
Now I need decimal value(03405122) to store it into integer variable
int decimalValue=03405122;
With this decimal value I want to verify with some number which is given by business.
Let's take some number as 45.
now I have to verify decimalValue until it meets the below condition
03405122<=45 if yes just take the decimal value
if no then remove the 1st digit from left side until condition satisfiet
3405122<=45
405122<=45
05122<=45
5122<=45
122<=45
22<=45.
So, 22 is the number I have to take for further implementation.
This is the code which I have written, and give me some suggestions that If I can write in a better way.
// Extracting Decimal value
public int extractDecimal(int computeRandomNumber)
{
int _computeRandom = computeRandomNumber;
double sqrt = Math.sqrt(_computeRandom);
BigDecimal df;
df = round(sqrt, 8);
// System.out.println(df);
String sqrt_round = String.valueOf(df);
// System.out.println(sqrt_round);
int index = sqrt_round.lastIndexOf('.') + 1;
String sqrt_round_deci = sqrt_round.substring(index);
// System.out.println(sqrt_round_deci);
return Integer.parseInt(sqrt_round_deci);
}
//Comparing with the some number to find the random number
public int findRandomNumber(int value, int totalRange) {
int _val;
System.out.println("calling rec::: val:" + value);
if (value <= totalRange) {
System.out.println("Success... returing on final value:" + value);
return value;
}
String new_str = String.valueOf(value);
String final_str = new_str.substring(1);
// System.out.println("str:"+final_str);
int val = Integer.parseInt(final_str);
// System.out.println("val:"+val);
_val = findRandomNumber(val, totalRange);
return _val;
// System.out.println("Returning flag:"+flag);
}
Thanks in Advance!
As you provided a pseudo-code only question, I will be generous and provide a pseudo-code only answer:
1) Get the String value of sqrt_val
2) Use the substring() method to get only the places1 after the .
3) Loop through the length2 of said substring
4) Check on each iteration if the valueOf your String is less than your target
5a) If so, there's your result
5b) If not, get the substring starting from position 1
1 If this begins with a 0, your results may vary so I'll leave this for you to work out
2 If you use this way, be careful if your loop goes via String.length as you use a substring in the else
I am in no way convinced that this is the best solution but here's an alternative solution which doesn't use Strings.
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
// Value to be less than
BigDecimal lessThan = new BigDecimal(80);
int test = 333444;
BigDecimal bd = new BigDecimal( Math.sqrt(test) );
System.out.println(bd);
while( bd.scale() > 0 ) {
// get the fractional value and make it a whole number
BigDecimal fractionOnly = bd.divideAndRemainder(BigDecimal.ONE)[1];
fractionOnly = fractionOnly.movePointRight(fractionOnly.scale());
// do the check
System.out.println( fractionOnly + " < " + lessThan );
if ( fractionOnly.compareTo( lessThan ) < 0 ) {
System.out.println( "Yes" );
break;
}
// method kinda says it
bd = bd.movePointRight(1);
}
}
}

Format for number with floating point

I want to implement format with dynamic floating point for different length of input data in specified length for display. For example x.xxxx, xx.xxxx, xxx.xx, xxxx.x.
In other words,
if I have 1.4, I need 1.4000.
if 13.4 then I need 13.400, for every case length should be 5 digits (with no dot).
I'm using
DecimalFormat df2 = new DecimalFormat("000000");
but can't build a correct pattern. Is there any solution for this?
Thanks for helping.
The following is not production code. It doesn’t take a leading minus into account, nor very high values of the noDigits constant. But I believe you can use it as a starting point. Thanks to Mzf for inspiration.
final static int noDigits = 5;
public static String myFormat(double d) {
if (d < 0) {
throw new IllegalArgumentException("This does not work with a negative number " + d);
}
String asString = String.format(Locale.US, "%f", d);
int targetLength = noDigits;
int dotIx = asString.indexOf('.');
if (dotIx >= 0 && dotIx < noDigits) {
// include dot in result
targetLength++;
}
if (asString.length() < targetLength) { // too short
return asString + "0000000000000000000000".substring(asString.length(), targetLength);
} else if (asString.length() > targetLength) { // too long
return asString.substring(0, targetLength);
}
// correct length
return asString;
}

Math with bigdecimal resulting in 0

I'm trying to figure a problem out with BigDecimal. My code:
BigDecimal tweetcount = new BigDecimal(3344048);
BigDecimal emotionCountBig = new BigDecimal(855937);
BigDecimal emotionCountSentenceBig = new BigDecimal(84988);
MathContext mc = new MathContext(64);
PMI[cnt] = (emotionCountSentenceBig.divide((tweetcount.multiply(emotionCountBig,mc)),RoundingMode.HALF_UP));
What I'd like to do is: emotionCountSentenceBig/(emotionCountBig*tweetcount)
(The values can be bigger)
If i try this I get a zero, which is not possible. Any help ?
You need to specify the MathContext for the division too:
emotionCountSentenceBig.divide(tweetcount.multiply(emotionCountBig, mc), mc);
That gives the expected result:
2.969226352632111794036880818610913852084810652372969382467557947E-8
Now as rightly commented by #PeterLawrey you could use doubles instead:
public static void main(String[] args) throws Exception {
double tweetcount = 3344048;
double emotionCount = 855937;
double emotionCountSentence = 84988;
double result = emotionCountSentence / (tweetcount * emotionCount);
System.out.println("result = " + result);
}
which prints:
result = 2.9692263526321117E-8
Note that if you use:
double result = 84988 / (3344048 * 855937);
you are actually doing your operations (* and /) on integer and it will return 0. You can prevent it by explicitly using a double, for example (note the d):
double result = 84988d / (3344048d * 855937);
I would use double
int tweetcount = 3344048;
int emotionCountBig = 855937;
int emotionCountSentenceBig = 84988;
double pmi = emotionCountSentenceBig/((double) tweetcount * emotionCountBig);
System.out.println(pmi);
prints
2.9692263526321117E-8
which is close to the answer using BigDecimal
2.969226352632111794036880818610913852084810652372969382467557947E-8

Categories