Java get without rounding first 2 decimal digits of a double - java

I want to get the first 2 decimal digits (without rounding ).
Here is an example:
49455.10937 --> 49455.10

formatting to String is an expensive operation (in performance terms)
this can be done with math operations:
double x = 49455.10937;
x *= 100; // moves two digits from right to left of dec point
x = Math.floor(x); // removes all reminaing dec digits
x /= 100; // moves two digits from left to right of dec point

double decimalValue = 49455.10937;
String decimalValueStr = String.valueOf(decimalValue);
int indexDot = decimalValueStr.lastIndexOf('.');
int desiredDigits=3;
String decimal = decimalValueStr.substring(0, (indexDot + 1) + desiredDigits);
decimalValue = Double.parseDouble(decimal);
System.out.println(decimalValue);
//49455.109 is console output (change desired digits)

You can use a formatter to format the double value as follows
StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter(sb, Locale.US);
Double value = 49455.10937;
System.out.println(formatter.format("The value: %.2f", value));

Related

How to remove the "0," in a fraction in Java?

I have a float value of a current weight like e.g. "79.3" kilograms.
I split the float value into a kilogram and a grams value.
I get the right amount of kilograms when parsing the float-value to int.
Then I get the fractional part of the float-value. This fractional part looks like "0,3" which means 0.3 kilograms or 300grams.
In my Programm I can only have 0,100,200,..,900 Grams which would stand for 0-9.
My goal is to remove the "0," so I only get the value of "3".
This is my code for now and I tried some decimal formatting too, but I didn't know how to do it:
public void setCurrentWeightInTheNumberPickers() {
float currentWeightAsFloat = weight_dbHandler.getCurrentWeightFloat();
int currentWeightKilograms = (int) currentWeightAsFloat;
double fractionOfGrams = currentWeightAsFloat % 1;
DecimalFormat df1 = new DecimalFormat("0.##");
String rounded = df1.format(fractionOfGrams);
rounded.replaceFirst("^0+(?!$)", "");
} //public void setCurrentWeightInTheNumberPickers()
Given a string
String gram = "0,3";
you can just do:
gram = gram.substring(gram.lastIndexOf(",") + 1);
which gives the following output when printed
3
Or you can simply do that. No need for strings.
float f = 3.3f;
int g = (int)f;
int h = Math.round((f - g)*10);
and since h is supposed to be grams, you might as well make it *1000
I view this primarily as a math, not a Java, problem. Given a float input in units of kilograms, to obtain only the kilogram component, we can take the floor. To get the grams component, we can multiply by 1000 and then take the mod of 1000.
double input = 79.321;
double kg = Math.floor(input);
System.out.println("kilograms: " + kg);
double g = Math.floor((1000*input) % 1000);
System.out.println("grams: " + g);
kilograms: 79.0
grams: 321.0
Note: I am using double here instead of float, only because Math.floor returns double as its return value.

Get a numer decimal part as Integer using only math

Edit: This has to do with how computers handle floating point operations, a fact that every programmer faces once in a lifetime. I didn't understand this correctly when I asked the question.
I know the simplest way to start dealing with this would be:
val floatNumber: Float = 123.456f
val decimalPart = floatNumber - floatNumber.toInt() //This would be 0.456 (I don't care about precision as this is not the main objective of my question)
Now in a real world with a pen and a piece of paper, if I want to "convert" the decimal part 0.456 to integer, I just need to multiply 0.456 * 1000, and I get the desired result, which is 456 (an integer number).
Many proposed solutions suggest splitting the number as string and extracting the decimal part this way, but I need the solution to be obtained mathematically, not using strings.
Given a number, with an unknown number of decimals (convert to string and counting chars after . or , is not acceptable), I need to "extract" it's decimal part as an integer using only math.
Read questions like this with no luck:
How to get the decimal part of a float?
How to extract fractional digits of double/BigDecimal
If someone knows a kotlin language solution, it would be great. I will post this question also on the math platform just in case.
How do I get whole and fractional parts from double in JSP/Java?
Update:
Is there a "mathematical" way to "calculate" how many decimals a number has? (It is obvious when you convert to string and count the chars, but I need to avoid using strings) It would be great cause calculating: decimal (0.456) * 10 * number of decimals(3) will produce the desired result.
Update 2
This is not my use-case, but I guess it will clarify the idea:
Suppose you want to calculate a constant(such as PI), and want to return an integer with at most 50 digits of the decimal part of the constant. The constant doesn't have to be necessarily infinite (can be for example 0.5, in which case "5" will be returned)
I would just multiply the fractional number by 10 (or move the decimal point to the right) until it has no fractional part left:
public static long fractionalDigitsLong(BigDecimal value) {
BigDecimal fractional = value.remainder(BigDecimal.ONE);
long digits;
do {
fractional = fractional.movePointRight(1); // or multiply(BigDecimal.TEN)
digits = fractional.longValue();
} while (fractional.compareTo(BigDecimal.valueOf(digits)) != 0);
return digits;
}
Note 1: using BigDecimal to avoid floating point precision problems
Note 2: using compareTo since equals also compares the scale ("0.0" not equals "0.00")
(sure the BigDecimal already knows the size of the fractional part, just the value returned by scale())
Complement:
If using BigDecimal the whole problem can be compressed to:
public static BigInteger fractionalDigits(BigDecimal value) {
return value.remainder(BigDecimal.ONE).stripTrailingZeros().unscaledValue();
}
stripping zeros can be suppressed if desired
I am not sure if it counts against you on this specific problem if you use some String converters with a method(). That is one way to get the proper answer. I know that you stated you couldn't use String, but would you be able to use Strings within a Custom made method? That could get you the answer that you need with precision. Here is the class that could help us convert the number:
class NumConvert{
String theNum;
public NumConvert(String theNum) {
this.theNum = theNum;
}
public int convert() {
String a = String.valueOf(theNum);
String[] b = a.split("\\.");
String b2 = b[1];
int zeros = b2.length();
String num = "1";
for(int x = 0; x < zeros; x++) {
num += "0";
}
float c = Float.parseFloat(theNum);
int multiply = Integer.parseInt(num);
float answer = c - (int)c;
int integerForm = (int)(answer * multiply);
return integerForm;
}
}
Then within your main class:
public class ChapterOneBasics {
public static void main(String[] args) throws java.io.IOException{
NumConvert n = new NumConvert("123.456");
NumConvert q = new NumConvert("123.45600128");
System.out.println(q.convert());
System.out.println(n.convert());
}
}
output:
45600128
456
Float or Double are imprecise, just an approximation - without precision. Hence 12.345 is somewhere between 12.3449... and 12.3450... .
This means that 12.340 cannot be distinghuished from 12.34. The "decimal part" would be 34 divided by 100.
Also 12.01 would have a "decimal part" 1 divided by 100, and too 12.1 would have 1 divided by 10.
So a complete algorith would be (using java):
int[] decimalsAndDivider(double x) {
int decimalPart = 0;
int divider = 1;
final double EPS = 0.001;
for (;;) {
double error = x - (int)x;
if (-EPS < error && error < EPS) {
break;
}
x *= 10;
decimalPart = 10 * decimalPart + ((int)(x + EPS) % 10);
divider *= 10;
}
return new int[] { decimalPart, divider };
}
I posted the below solution yesterday after testing it for a while, and later found that it does not always work due to problems regarding precision of floats, doubles and bigdecimals. My conclusion is that this problem is unsolvable if you want infinite precision:
So I re-post the code just for reference:
fun getDecimalCounter(d: Double): Int {
var temp = d
var tempInt = Math.floor(d)
var counter = 0
while ((temp - tempInt) > 0.0 ) {
temp *= 10
tempInt = Math.floor(temp)
counter++
}
return counter
}
fun main(args: Array <String> ) {
var d = 3.14159
if (d < 0) d = -d
val decimalCounter = getDecimalCounter(d)
val decimalPart = (d - Math.floor(d))
var decimalPartInt = Math.round(decimalPart * 10.0.pow(decimalCounter))
while (decimalPartInt % 10 == 0L) {
decimalPartInt /= 10
}
println(decimalPartInt)
}
I dropped floats because of lesser precision and used doubles.
The final rounding is also necessary due to precision.

Display 2 floats rounded up to 2 decimal places without losing which one is bigger

I get two numbers num1 and num2 from a network service that can be represented by a double and have an unknown number of decimal places (I mean could be 3, 4 or 5 etc).
These numbers represent a percentage so could be something like 0.34567 which is 34.567%
I need to display them with 2 decimal places (or no decimal places instead of e.g. 34.00%) if num1 is greater than num2.
I tried the following:
String num1 = "0.3547";
String num2 = "0.354";
int fixed = 2;
int diff = Math.abs(num1.length() - num2.length());
double tmp = 0.0d;
double d1 = Double.valueOf(num1);
double d2 = Double.valueOf(num2);
tmp = (d1 > d2)? d1 : d2;
while(diff > 0) {
StringBuilder sb = new StringBuilder("%.");
sb.append(String.valueOf(fixed + diff)).append("f");
String formatter = sb.toString();
System.out.println(formatter);
String round = String.format(formatter, tmp);
tmp = Double.parseDouble(round);
--diff;
}
String final1 = String.format("%.2f", tmp);
String final2 = String.format("%.2f", (d1 < d2)? d1 : d2);
System.out.println(final1 + " vs " + final2);
The output is:
0.36 vs 0.35
How sane is this approach and the result? May be I am thinking this wrong?
For ceation of two decimal places just do:
num = (Maht.round(num * 10_000))
num /= 10_000
If you just divide by 100 instead of 10_000 you get directly percent.
and for removing zeros just convert the number to a String with
String.valueOf(num)
and search for the regex pattern
"\\.0"
and act accordingly by removing it if it is found.
Complet solution (a bit diffrent, because I had some trouble with regex):
//Rounding on to two decimalplaces and writing to a String
numX = (Math.round(numX * 10_000));
String numXStr = String.valueOf(numX /= 100);
//Removing of ".0" endings
if (numXStr .endsWith(".0")) {
numXStr = numXStr .substring(0, numXStr .length() - 2);
}
numXStr += "%"; //Adding the percent char at the end
System.out.println(numXStr) //outputting

Retrieve numbers after comma (from double numbers)

Imagine that I have 4,81 (double), how can i get the figures after the comma?
I want to receive 8 as a Integer and 1 as another.
Thanks
Doubles are tricky to work with when you're interested in decimal properties such as the decimal digits of the fractional part.
I suggest you let String.valueOf do the transformation to decimal digits and work with the resulting string.
double d = 4.81;
String s = String.valueOf(d);
for (int i = s.indexOf(".") + 1; i < s.length(); i++) {
int digit = Character.getNumericValue(s.charAt(i));
System.out.println(digit);
}
Output:
8
1
You can always make this kind of loop:
double number = 4,81;
while (condition) {
number *= 10;
int nextNumber = Math.floor(number) % 10;
}

Rounding a double down (even when the previous calculation results in < .5)

I'm trying to round the number down despite the value after the decimal point. The purpose is then to subtract the rounded number from the full number to isolate the decimals as a new value.
DecimalFormat decfom = new DecimalFormat("#.##");
String splitter1 = decfom.format(newdecihole);
DecimalFormat df = new DecimalFormat("##.");
String splitter2 = df.format(newdecihole);
double split1 = Double.parseDouble(splitter1);
double split2 = Double.parseDouble(splitter2);
double splitdeci = split1 - split2;
double finfracti = splitdeci * 8;
What im trying to do is turn the result into whole numbers and 8ths. Everything ive tried works fine until I have a result that rounds up instead of down (which then gives splitdeci a negative value).
Ive tried making split 2 an int but it just rounds it up
Are you looking for
Math.floor
?
http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html#floor(double)
double splitDecimal = split1 - Math.floor(split2);
int eightFraction = Math.round(splitDecimal) * 8;

Categories