Java equivalent of Oracle's TRUNC function? - java

In my PL-SQL work, I've come to regularly use the TRUNC function to check higher-position values in numeric IDs. for example:
if trunc(idValue,-3)=254000 then...
Is there a similar method available for int/Integer variables in Java?

You could take advantage of integer division here:
public int trunc(int value, int places) {
// places should be positive, not negative
int divisor = Math.pow(10, places);
int tempVal = value / divisor;
int finalVal = tempVal * divisor;
return finalVal;
}
(somewhere in your code)
if (trunc(idValue,3)==254000)

Related

Calculating a BigDecimal results in inaccurate answer

So I just wanted to screw around to see if I can make it so I can calculate E, but instead have it so I can have dynamic degrees of precision. While I did technically accomplish it, no matter what int i put in for the variable PRECISION, the last few numbers are always different from what the actual value of E is suppose to be. I'm not entirely sure why, but help would be appreciated.
import java.math.BigDecimal; //To use for calculating E
public class ComputeE {
public static double calcDenominator(int n)
{
double denominator = 1.0; //Start the BigInt with 1
for(int i = 1; i < n; i++) // Run n-1 amount of times
{
denominator = denominator * i; // Multiply BigInteger by the BigInteger obtained with the int value i
}
return denominator;
}
public static void main(String[] args) {
BigDecimal e = new BigDecimal(0.0);
int PRECISION = 15;
int iterations = 0;
for(int i = 0; i < PRECISION; i++)
{
iterations++;
BigDecimal numerator = new BigDecimal(1.0); // to divide, we need two BigDecimals, the numerator is 1
BigDecimal factorial = new BigDecimal(calcDenominator(i)); // the denominator is i! which we get from calling the factorial method
factorial = numerator.divide(factorial, PRECISION, BigDecimal.ROUND_UNNECESSARY); // compute 1/i!, note divide is overloaded, this version is used to
// ensure a limit to the iterations when division is limitless like 1/3
e = e.add(factorial); // add the latest 1/i! to e
}
System.out.println("Computed value of e : " + e);
System.out.println("Expected value of e : " + Math.E);
}
}
Rounding is necessary here. Use something like HALF_EVEN. Even better, use the enum value RoundingMode.HALF_EVEN, because the integer constants for rounding mode are deprecated.
In calcDenominator, change your for loop condition to i <= n, or else you'll add 1 one too many times in main and you'll get a value that's 1 too high.
You can use BigDecimal.ONE to initialize numerator. This doesn't affect the result, but why create an unnecessary object? Same comment on the initialization of e, except with BigDecimal.ZERO.
You are using the first PRECISION terms of an infinite series (Maclaurin Series) that approximates e, an irrational number. There is an error term when you cut off the for loop, and that is expected mathematically. With the above changes, and bumping PRECISION to 50, I get the following, which looks sufficiently precise.
Computed value of e : 2.71828182845904523536028747135266249775496954201584
Expected value of e : 2.718281828459045
It is precise, despite using the double constructor for BigDecimal because the significant digits for a double start with the first non-zero bit, so even if you're calculating 1/n! for large n, the significant digits are good enough for adding to the existing approximation for e.

Calculation the average of short type array in JAVA

Let's say I have a short[] thisArray in JAVA, and I need to calculate the average based on the amount of elements in this array. But apparently, .length will return a int number to represent the length of thisArray.
I cannot convert it into int Array or int, since it is not allowed to convert int back to short. I do need to have a short result and store back into another short[][].
How to avoid this classic error:
error: incompatible types: possible lossy conversion from int to short
short result = sum / thisArray.length;
public static short getSum(short[] sumArray) {
short sum = 0;
for(short i : sumArray) {
sum += i;
}
return sum;
}
sum = getSum(thisArray);
short result = sum / thisArray.length;
If you know for sure the average can fit into a short variable, you just have to cast the result:
short result = (short)(sum / thisArray.length);
I'd also change sum to int, to reduce the risk of overflow (which may occur if the sum is larger than 32767).
To summarize:
public static int getSum(short[] sumArray) {
int sum = 0;
for(short i : sumArray) {
sum += i;
}
return sum;
}
...
int sum = getSum(thisArray);
short result = (short) (sum / thisArray.length);
You need to explicitly cast the result
short result = (short)( sum / thisArray.length );
The compiler is protecting you from losing data when you assign an int value to a short variable. Providing the cast is the usual way of telling the compiler that you know what you're doing, and this operation is OK.

Need of typecasting before ceil

I am going through the following code in Java:
public float a1 = 0.10f;
int Increments;
if(TotalTime > 0)
{
Increments = (int) ceil(TotalTime / Increment1);
amount = round(Increments * a1, 4);
}
Where,
TotalTime and Increment1 are integers
My questions is, Why do we need to typecast to integer just before ceil as done in the following line of code above?
Increments = (int) ceil(TotalTime / Increment1);
Because Math.ceil (I suppose it's a static import there) returns a double. As you make a restriction of the converted value (by converting to a less precise type), you need to do the conversion explicitly.
Also, please note that the argument you pass to ceil is the ratio of two integers, which is also an integer. So you're in danger of losing precision. Moreover, applying ceil to an integer is redundant, as it will return that integer itself. And the last remark: ceil expects a double as its argument. In this case, you pass an int, but the conversion is done implicitly, because it is done from a less precise to a more precise type.
The reason is that Math.ceil returns a double. You cannot implicitly cast from a double to an int. Trying to compile this:
double d = 2.1;
int i = d;
Gives you:
dur.java:4: possible loss of precision
found : double
required: int
int i = d;
^
1 error
As the error message states, the reason is that you might lose precision, so the compiler wants to be sure that you really want to allow this loss. You do this by making the cast explicit:
int i = (int)d;
Note that even so, your code won't do what you expect.
int i = 10;
int j = 3;
int k = (int)Math.ceil(i/j);
System.out.println(k); //outputs '3'
The reason is that i / j performs integer division if both i and j are integers, which rounds down. i / j is already 3, and all Math.ceil does is return 3.0, which then again gets casted to 3. You want to do floating point division instead, which is done when one or both of i and j are floating point types. You can achieve this by casting one of the integers to a double before doing the division:
int i = 10;
int j = 3;
int k = (int)Math.ceil((double)i/j);
System.out.println(k); //outputs '4'

How to test if a double is an integer

Is it possible to do this?
double variable;
variable = 5;
/* the below should return true, since 5 is an int.
if variable were to equal 5.7, then it would return false. */
if(variable == int) {
//do stuff
}
I know the code probably doesn't go anything like that, but how does it go?
Or you could use the modulo operator:
(d % 1) == 0
if ((variable == Math.floor(variable)) && !Double.isInfinite(variable)) {
// integer type
}
This checks if the rounded-down value of the double is the same as the double.
Your variable could have an int or double value and Math.floor(variable) always has an int value, so if your variable is equal to Math.floor(variable) then it must have an int value.
This also doesn't work if the value of the variable is infinite or negative infinite hence adding 'as long as the variable isn't inifinite' to the condition.
Guava: DoubleMath.isMathematicalInteger. (Disclosure: I wrote it.) Or, if you aren't already importing Guava, x == Math.rint(x) is the fastest way to do it; rint is measurably faster than floor or ceil.
public static boolean isInt(double d)
{
return d == (int) d;
}
Try this way,
public static boolean isInteger(double number){
return Math.ceil(number) == Math.floor(number);
}
for example:
Math.ceil(12.9) = 13; Math.floor(12.9) = 12;
hence 12.9 is not integer, nevertheless
Math.ceil(12.0) = 12; Math.floor(12.0) =12;
hence 12.0 is integer
Here is a good solution:
if (variable == (int)variable) {
//logic
}
Consider:
Double.isFinite (value) && Double.compare (value, StrictMath.rint (value)) == 0
This sticks to core Java and avoids an equality comparison between floating point values (==) which is consdered bad. The isFinite() is necessary as rint() will pass-through infinity values.
Here's a version for Integer and Double:
private static boolean isInteger(Double variable) {
if ( variable.equals(Math.floor(variable)) &&
!Double.isInfinite(variable) &&
!Double.isNaN(variable) &&
variable <= Integer.MAX_VALUE &&
variable >= Integer.MIN_VALUE) {
return true;
} else {
return false;
}
}
To convert Double to Integer:
Integer intVariable = variable.intValue();
Similar to SkonJeet's answer above, but the performance is better (at least in java):
Double zero = 0d;
zero.longValue() == zero.doubleValue()
My simple solution:
private boolean checkIfInt(double value){
return value - Math.floor(value) == 0;
}
public static boolean isInteger(double d) {
// Note that Double.NaN is not equal to anything, even itself.
return (d == Math.floor(d)) && !Double.isInfinite(d);
}
A simple way for doing this could be
double d = 7.88; //sample example
int x=floor(d); //floor of number
int y=ceil(d); //ceil of number
if(x==y) //both floor and ceil will be same for integer number
cout<<"integer number";
else
cout<<"double number";
My solution would be
double variable=the number;
if(variable-(int)variable=0.0){
// do stuff
}
you could try in this way: get the integer value of the double, subtract this from the original double value, define a rounding range and tests if the absolute number of the new double value(without the integer part) is larger or smaller than your defined range. if it is smaller you can intend it it is an integer value. Example:
public final double testRange = 0.2;
public static boolean doubleIsInteger(double d){
int i = (int)d;
double abs = Math.abs(d-i);
return abs <= testRange;
}
If you assign to d the value 33.15 the method return true. To have better results you can assign lower values to testRange (as 0.0002) at your discretion.
Personally, I prefer the simple modulo operation solution in the accepted answer.
Unfortunately, SonarQube doesn't like equality tests with floating points without setting a round precision. So we have tried to find a more compliant solution. Here it is:
if (new BigDecimal(decimalValue).remainder(new BigDecimal(1)).equals(BigDecimal.ZERO)) {
// no decimal places
} else {
// decimal places
}
Remainder(BigDecimal) returns a BigDecimal whose value is (this % divisor). If this one's equal to zero, we know there is no floating point.
Because of % operator cannot apply to BigDecimal and int (i.e. 1) directly, so I am using the following snippet to check if the BigDecimal is an integer:
value.stripTrailingZeros().scale() <= 0
Similar (and probably inferior) to Eric Tan's answer (which checks scale):
double d = 4096.00000;
BigDecimal bd = BigDecimal.valueOf(d);
String s = bd.stripTrailingZeros().toPlainString();
boolean isInteger = s.indexOf(".")==-1;
Here's a solution:
float var = Your_Value;
if ((var - Math.floor(var)) == 0.0f)
{
// var is an integer, so do stuff
}

Are there any functions for truncating a double in java?

Is there a Java Library function which can be used to truncate a number to an arbitrary number of decimal places?
For Example.
SomeLibrary.truncate(1.575, 2) = 1.57
Thanks
Try setScale of BigDecimal like so:
public static double round(double d, int decimalPlace) {
BigDecimal bd = new BigDecimal(d);
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
}
Incredible no one brought this up yet, Java API has had DecimalFormat for ages now for this exact purpose.
For most numbers, you won't be able to get an exact representation of xxx.yyyy unless you use a decimal class with guaranteed accuracy, such as BigDecimal.
There's one in commons-math. Check out http://commons.apache.org/math/apidocs/org/apache/commons/math/util/MathUtils.html:
public static double round(double x,
int scale)
It's implemented using BigDecimal, and is overloaded to allow specifying a rounding method, so you can use it to truncate, like this:
org.apache.commons.math.util.MathUtils.round(1.575, 2,
java.math.BigDecimal.ROUND_DOWN);
Update:
In the last version (Math3), this method is in the class Precision.
org.apache.commons.math3.util.Precision.round(double x, int scale, int roundingMethod)
Simply remove the fractional portion
public double trunk(double value){
return value - value % 1;
}
Use this simple function
double truncateDouble(double number, int numDigits) {
double result = number;
String arg = "" + number;
int idx = arg.indexOf('.');
if (idx!=-1) {
if (arg.length() > idx+numDigits) {
arg = arg.substring(0,idx+numDigits+1);
result = Double.parseDouble(arg);
}
}
return result ;
}
I just want to add to ubuntudroid's solution.
I tried it and it wouldn't round down, so I had to add
df.setRoundingMode(RoundingMode.FLOOR);
for it to work.
here is a short implementation which is many times faster than using BigDecimal or Math.pow
private static long TENS[] = new long[19];
static {
TENS[0] = 1;
for (int i = 1; i < TENS.length; i++) TENS[i] = 10 * TENS[i - 1];
}
public static double round(double v, int precision) {
assert precision >= 0 && precision < TENS.length;
double unscaled = v * TENS[precision];
if(unscaled < Long.MIN_VALUE || unscaled > Long.MAX_VALUE)
return v;
long unscaledLong = (long) (unscaled + (v < 0 ? -0.5 : 0.5));
return (double) unscaledLong / TENS[precision];
}
Delete the assert'ions to taste. ;)
Actually, this sort of thing is easy to write:
public static double truncate(double value, int places) {
double multiplier = Math.pow(10, places);
return Math.floor(multiplier * value) / multiplier;
}
Note that it's Math.floor, because Math.round wouldn't be truncating.
Oh, and this returns a double, because that's what most functions in the Math class return (like Math.pow and Math.floor).
Caveat: Doubles suck for accuracy. One of the BigDecimal solutions should be considered first.
To do it 100% reliably, you'd have to pass the argument as string, not as floating-point number. When given as string, the code is easy to write. The reason for this is that
double x = 1.1;
does not mean that x will actually evaluate to 1.1, only to the closest exactly representable number.
created a method to do it.
public double roundDouble(double d, int places) {
return Math.round(d * Math.pow(10, (double) places)) / Math.pow(10, (double)places);
}

Categories

Resources