I'm a beginning programmer and I need a method that returns whether or not a double is an integer. The problem occurs when the number is too big for an int to hold.
Here's what I have:
private static boolean isInteger(double n){
int ni = (int) n;
double nd = (double) ni;
if (nd==n)
return true;
return false;
}
Say I put in like 143215890634.0. It will return false because the int can't store that many digits.
How can I allow the int(or another class) to store more digits or is there a better way to determine if a double is an int without comparing like this?
Thanks in advance!
Well long holds more digits than int. By the time you get outside the range of long, all double values are integers (and separated by more than 1). So you could use something like:
private static boolean isInteger(double n) {
if (n > (double) Long.MAX_VALUE || n < (double) Long.MIN_VALUE) {
return true;
}
long asLong = (long) n;
return n == (double) asLong;
}
There are alternative approaches which would determine the bitwise representation, and check the exponent - but they'd be more complicated, at least to understand.
Note that checking for exact values in binary floating point is usually a bad idea. You might instead want to check how close the double to the nearest integer, and have some sort of tolerance.
try
boolean isInteger(double d) {
return d % 1 == 0;
}
Compare it to Integer.MAX_VALUE. If it is smaller - it will fit into integer assuming it has no fraction.
To store lager numbers you would have to use long instead. As for the comparison, you could maybe do num == Math.round(num) instead.
I suppose, this would work even better than Math.round(), since it avoids type promotion:
double d1 = 143215890634.0, d2 = 143215890634.001;
System.out.println(d1 == Math.floor(d1));
System.out.println(d2 == Math.floor(d2));
This works, if with "integer" you don't mean actual type "int", but a "number without position after decimal point".
Related
I want to find whether a given number is a power of two in a mathematical way, not with a bitwise approach. Here is my code:
private static double logBaseTwo(final double x) {
return Math.log(x) / Math.log(2);
}
private static double roundToNearestHundredThousandth(final double x) {
return Math.round(x * 100000.0) / 100000.0;
}
private static boolean isInteger(final double x) {
return (int)(Math.ceil(x)) == (int)(Math.floor(x));
}
public static boolean isPowerOfTwo(final int n) {
return isInteger(roundToNearestHundredThousandth(logBaseTwo(n)));
}
It incorrectly returns true for certain numbers, such as 524287. Why is that?
Your code fails because you may need more precision than you allow to capture the difference between the logs of BIG_NUMBER and BIG_NUMBER+1
The bitwise way is really best, but if you really want to use only "mathy" operations, then the best you can do is probably:
public static boolean isPowerOfTwo(final int n) {
int exp = (int)Math.round(logBaseTwo(n));
int test = (int)Math.round(Math.pow(2.0,exp));
return test == n;
}
This solution does not require any super-fine precision, and will work fine for all positive ints.
This is truly horrifyingly bad code, and I have no idea what you are trying to do. You seem to be trying to check if the log base 2 of n is an integer. Instead I would write a loop:
while (n>1) {
m = (n/2) * 2
if (n!=m){
return false;
}
n /=2;
}
return true;
The solution seems more complicated than it should be. I don't get the 100000d parts - seems to potentially cause problems when converting to ceiling.
This is the simple solution that works for all cases:
public static boolean isPowerOfTwo(int n) {
return Math.ceil(Math.log(n)/Math.log(2)) == Math.floor(Math.log(n)/Math.log(2));
}
Originally I had a problem using Math.log in my computations. I switched to Math.log10 and the problem went away. Although mathematically, any logB of base B should work, the nature of floating point math can be unpredictable.
Try this.
public static boolean isPowerOfTwo(int n) {
return n > 0 && Integer.highestOneBit(n) == Integer.lowestOneBit(n);
}
If you prefer to use logs you can do it this way.
public static boolean isPowerOfTwo(int n) {
return n > 0 && (Math.log10(n)/Math.log10(2))%1 == 0;
}
doubles and floats have, respectively, 64-bit and 32-bit precision. That means they can hold at the very most 18446744073709551616 unique numbers. That's a lot of numbers, but not an infinite amount of them. At some point (in fact, that point occurs about at 2^52), the 'gap' between any 2 numbers which are part of the 18446744073709551616 representable ones becomes larger than 1.000. Similar rules apply to small numbers. Math.log does double based math.
Secondarily, ints are similarly limited. They can hold up to 4294967296 different numbers. For ints it's much simpler: Ints can hold from -2147483648 up to 2147483647. If you try to add 1 to 2147483647, you get -2147483648 (it silently wraps around). It's quite possible you're running into that with trying to convert such a large number (your double times 10000d) to an int first.
Note that ? true : false (as in the original version of the question) is literally completely useless. the thing to the left of the question mark must be a boolean, and booleans are already true or false, that's their nature.
See the other answers for simpler approaches to this problem. Although, of course, the simplest solution is to simply count bits in the number. If it's precisely 1 bit, it's a power of 2. If it's 0 bits, well, you tell me if you consider '0' a power of 2 :)
I am trying to create a recursive method to compute a series in java 1/i.
Here is my code:
public static double computeSeries(int n) {
if (n == 1)
return 1;
else
return (1/n) + computeSeries(n - 1);
}
where 'n' is passed through the main method. However it doesn't exactly work correctly. FE when I type in 3, it returns 2.0, where I calculated it to be 1.8, and if I use 2, it gives me 1.0
While you're going to work with decimals, you might at least want to have a double as input
Solution
public static double computeSeries(double n)
However, if you only want the method to have an int as input, you might want to change 1/n to 1.0/n this will result to an operation of type double instead of int
This is called Promotion
JLS §5.6.2
If either operand is of type double, the other is converted to double.
First part of your result (1/n) is truncated to an int:
return (1/n) + computeSeries(n - 1);
Force calculations to be done in a double type by changing 1 to 1.0 (then it's a double):
return (1.0/n) + computeSeries(n - 1);
1/n
You are calculating in integers. This is always ZERO unless n == 1
Your first division will be 0 in most of the cases, since you're calculating with integers.
Instead use one of
return (1.0 / n) + computeSeries(n - 1);
return (1 / (double) n) + computeSeries(n - 1);
public static double computeSeries(double n) {
Bonus: You should take care of n = 0 to prevent a java.lang.ArithmeticException.
As most others have said, you need to convert the values to double before performing operations. Also, and this may just be personal preference, you may not want to have n calls of computeSeries running before they can all be completed.
Edit: After thinking more, using the for loop as I did below, there is no need for an extra method to calculate each term in the series. You can simply do the following
public static double computeSeries(int n) {
double sum = 0.0;
for(int i=1; i<=n; i++){
sum += (1.0/(double)i);
}
return sum;
}
Is there any way to find the absolute value of a number without using the Math.abs() method in java.
If you look inside Math.abs you can probably find the best answer:
Eg, for floats:
/*
* Returns the absolute value of a {#code float} value.
* If the argument is not negative, the argument is returned.
* If the argument is negative, the negation of the argument is returned.
* Special cases:
* <ul><li>If the argument is positive zero or negative zero, the
* result is positive zero.
* <li>If the argument is infinite, the result is positive infinity.
* <li>If the argument is NaN, the result is NaN.</ul>
* In other words, the result is the same as the value of the expression:
* <p>{#code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))}
*
* #param a the argument whose absolute value is to be determined
* #return the absolute value of the argument.
*/
public static float abs(float a) {
return (a <= 0.0F) ? 0.0F - a : a;
}
Yes:
abs_number = (number < 0) ? -number : number;
For integers, this works fine (except for Integer.MIN_VALUE, whose absolute value cannot be represented as an int).
For floating-point numbers, things are more subtle. For example, this method -- and all other methods posted thus far -- won't handle the negative zero correctly.
To avoid having to deal with such subtleties yourself, my advice would be to stick to Math.abs().
Like this:
if (number < 0) {
number *= -1;
}
Since Java is a statically typed language, I would expect that a abs-method which takes an int returns an int, if it expects a float returns a float, for a Double, return a Double. Maybe it could return always the boxed or unboxed type for doubles and Doubles and so on.
So you need one method per type, but now you have a new problem: For byte, short, int, long the range for negative values is 1 bigger than for positive values.
So what should be returned for the method
byte abs (byte in) {
// #todo
}
If the user calls abs on -128? You could always return the next bigger type so that the range is guaranteed to fit to all possible input values. This will lead to problems for long, where no normal bigger type exists, and make the user always cast the value down after testing - maybe a hassle.
The second option is to throw an arithmetic exception. This will prevent casting and checking the return type for situations where the input is known to be limited, such that X.MIN_VALUE can't happen. Think of MONTH, represented as int.
byte abs (byte in) throws ArithmeticException {
if (in == Byte.MIN_VALUE) throw new ArithmeticException ("abs called on Byte.MIN_VALUE");
return (in < 0) ? (byte) -in : in;
}
The "let's ignore the rare cases of MIN_VALUE" habit is not an option. First make the code work - then make it fast. If the user needs a faster, but buggy solution, he should write it himself.
The simplest solution that might work means: simple, but not too simple.
Since the code doesn't rely on state, the method can and should be made static. This allows for a quick test:
public static void main (String args []) {
System.out.println (abs(new Byte ( "7")));
System.out.println (abs(new Byte ("-7")));
System.out.println (abs((byte) 7));
System.out.println (abs((byte) -7));
System.out.println (abs(new Byte ( "127")));
try
{
System.out.println (abs(new Byte ("-128")));
}
catch (ArithmeticException ae)
{
System.out.println ("Integer: " + Math.abs (new Integer ("-128")));
}
System.out.println (abs((byte) 127));
System.out.println (abs((byte) -128));
}
I catch the first exception and let it run into the second, just for demonstration.
There is a bad habit in programming, which is that programmers care much more for fast than for correct code. What a pity!
If you're curious why there is one more negative than positive value, I have a diagram for you.
Although this shouldn't be a bottle neck as branching issues on modern processors isn't normally a problem, but in the case of integers you could go for a branch-less solution as outlined here: http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs.
(x + (x >> 31)) ^ (x >> 31);
This does fail in the obvious case of Integer.MIN_VALUE however, so this is a use at your own risk solution.
In case of the absolute value of an integer x without using Math.abs(), conditions or bit-wise operations, below could be a possible solution in Java.
(int)(((long)x*x - 1)%(double)x + 1);
Because Java treats a%b as a - a/b * b, the sign of the result will be same as "a" no matter what sign of "b" is; (x*x-1)%x will equal abs(x)-1; type casting of "long" is to prevent overflow and double allows dividing by zero.
Again, x = Integer.MIN_VALUE will cause overflow due to subtracting 1.
You can use :
abs_num = (num < 0) ? -num : num;
Here is a one-line solution that will return the absolute value of a number:
abs_number = (num < 0) ? -num : num;
-num will equal to num for Integer.MIN_VALUE as
Integer.MIN_VALUE = Integer.MIN_VALUE * -1
Lets say if N is the number for which you want to calculate the absolute value(+ve number( without sign))
if (N < 0)
{
N = (-1) * N;
}
N will now return the Absolute value
Currently i have this method:
static boolean checkDecimalPlaces(double d, int decimalPlaces){
if (d==0) return true;
double multiplier = Math.pow(10, decimalPlaces);
double check = d * multiplier;
check = Math.round(check);
check = check/multiplier;
return (d==check);
}
But this method fails for checkDecmialPlaces(649632196443.4279, 4) probably because I do base 10 math on a base 2 number.
So how can this check be done correctly?
I thought of getting a string representation of the double value and then check that with a regexp - but that felt weird.
EDIT:
Thanks for all the answers. There are cases where I really get a double and for those cases I implemented the following:
private static boolean checkDecimalPlaces(double d, int decimalPlaces) {
if (d == 0) return true;
final double epsilon = Math.pow(10.0, ((decimalPlaces + 1) * -1));
double multiplier = Math.pow(10, decimalPlaces);
double check = d * multiplier;
long checkLong = (long) Math.abs(check);
check = checkLong / multiplier;
double e = Math.abs(d - check);
return e < epsilon;
}
I changed the round to a truncation. Seems that the computation done in round increases the inaccuracy too much. At least in the failing testcase.
As some of you pointed out if I could get to the 'real' string input I should use BigDecimal to check and so I have done:
BigDecimal decimal = new BigDecimal(value);
BigDecimal checkDecimal = decimal.movePointRight(decimalPlaces);
return checkDecimal.scale() == 0;
The double value I get comes from the Apache POI API that reads excel files. I did a few tests and found out that although the API returns double values for numeric cells I can get a accurate representation when I immediately format that double with the DecimalFormat:
DecimalFormat decimalFormat = new DecimalFormat();
decimalFormat.setMaximumIntegerDigits(Integer.MAX_VALUE);
// don't use grouping for numeric-type cells
decimalFormat.setGroupingUsed(false);
decimalFormat.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));
value = decimalFormat.format(numericValue);
This also works for values that can't be represented exactly in binary format.
The test fails, because you have reached the accuracy of the binary floating point representation, which is approximately 16 digits with IEEE754 double precision. Multiplying by 649632196443.4279 by 10000 will truncate the binary representation, leading to errors when rounding and dividing afterwards, thereby invalidating the result of your function completely.
For more details see http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
A better way would be to check whether the n+1 decimal places are below a certain threshold. If d - round(d) is less than epsilon (see limit), the decimal representation of d has no significant decimal places. Similarly if (d - round(d)) * 10^n is less than epsilon, d can have at most n significant places.
Use Jon Skeet's DoubleConverter to check for the cases where d isn't accurate enough to hold the decimal places you are looking for.
If your goal is to represent a number with exactly n significant figures to the right of the decimal, BigDecimal is the class to use.
Immutable, arbitrary-precision signed
decimal numbers. A BigDecimal consists
of an arbitrary precision integer
unscaled value and a 32-bit integer
scale. If zero or positive, the scale
is the number of digits to the right
of the decimal point. If negative, the
unscaled value of the number is
multiplied by ten to the power of the
negation of the scale. The value of
the number represented by the
BigDecimal is therefore (unscaledValue
× 10-scale).
scale can be set via setScale(int)
As with all floating point arithmetic, you should not check for equality, but rather that the error (epsilon) is sufficiently small.
If you replace:
return (d==check);
with something like
return (Math.abs(d-check) <= 0.0000001);
it should work. Obviously, the epsilon should be selected to be small enough compared with the number of decimals you're checking for.
The double type is a binary floating point number. There are always apparent inaccuracies in dealing with them as if they were decimal floating point numbers. I don't know that you'll ever be able to write your function so that it works the way you want.
You will likely have to go back to the original source of the number (a string input perhaps) and keep the decimal representation if it is important to you.
If you can switch to BigDecimal, then as Ken G explains, that's what you should be using.
If not, then you have to deal with a host of issues as mentioned in the other answers. To me, you are dealing with a binary number (double) and asking a question about a decimal representation of that number; i.e., you are asking about a String. I think your intuition is correct.
I think this is better
Convert to string and interrogate the value for the exponent
public int calcBase10Exponet (Number increment)
{
//toSting of 0.0=0.0
//toSting of 1.0=1.0
//toSting of 10.0=10.0
//toSting of 100.0=100.0
//toSting of 1000.0=1000.0
//toSting of 10000.0=10000.0
//toSting of 100000.0=100000.0
//toSting of 1000000.0=1000000.0
//toSting of 1.0E7=1.0E7
//toSting of 1.0E8=1.0E8
//toSting of 1.0E9=1.0E9
//toSting of 1.0E10=1.0E10
//toSting of 1.0E11=1.0E11
//toSting of 0.1=0.1
//toSting of 0.01=0.01
//toSting of 0.0010=0.0010 <== need to trim off this extra zero
//toSting of 1.0E-4=1.0E-4
//toSting of 1.0E-5=1.0E-5
//toSting of 1.0E-6=1.0E-6
//toSting of 1.0E-7=1.0E-7
//toSting of 1.0E-8=1.0E-8
//toSting of 1.0E-9=1.0E-9
//toSting of 1.0E-10=1.0E-10
//toSting of 1.0E-11=1.0E-11
double dbl = increment.doubleValue ();
String str = Double.toString (dbl);
// System.out.println ("NumberBoxDefaultPatternCalculator: toSting of " + dbl + "=" + str);
if (str.contains ("E"))
{
return Integer.parseInt (str.substring (str.indexOf ("E") + 1));
}
if (str.endsWith (".0"))
{
return str.length () - 3;
}
while (str.endsWith ("0"))
{
str = str.substring (0, str.length () - 1);
}
return - (str.length () - str.indexOf (".") - 1);
}
Maybe it will be helpful. Here is my method
private int checkPrecisionOfDouble(Double atribute) {
String s = String.valueOf(atribute);
String[] split = s.split("\\.");
return split[1].length();
}
or
private boolean checkPrecisionOfDouble(Double atribute, int decimalPlaces) {
String s = String.valueOf(atribute);
String[] split = s.split("\\.");
return split[1].length() == decimalPlaces;
}
I'm not sure that this is really doable in general. For example, how many decimal places does 1.0e-13 have? What if it resulted from some rounding error while doing arithmetic and really is just 0 in disguise? If on, the other hand you are asking if there are any non-zero digits in the first n decimal places you can do something like:
static boolean checkDecimalPlaces(double d, unsigned int decimalPlaces){
// take advantage of truncation, may need to use BigInt here
// depending on your range
double d_abs = Math.abs(d);
unsigned long d_i = d_abs;
unsigned long e = (d_abs - d_i) * Math.pow(10, decimalPlaces);
return e > 0;
}
I have a Java method in which I'm summing a set of numbers. However, I want any negatives numbers to be treated as positives. So (1)+(2)+(1)+(-1) should equal 5.
I'm sure there is very easy way of doing this - I just don't know how.
Just call Math.abs. For example:
int x = Math.abs(-5);
Which will set x to 5.
Note that if you pass Integer.MIN_VALUE, the same value (still negative) will be returned, as the range of int does not allow the positive equivalent to be represented.
The concept you are describing is called "absolute value", and Java has a function called Math.abs to do it for you. Or you could avoid the function call and do it yourself:
number = (number < 0 ? -number : number);
or
if (number < 0)
number = -number;
You're looking for absolute value, mate. Math.abs(-5) returns 5...
Use the abs function:
int sum=0;
for(Integer i : container)
sum+=Math.abs(i);
Try this (the negative in front of the x is valid since it is a unary operator, find more here):
int answer = -x;
With this, you can turn a positive to a negative and a negative to a positive.
However, if you want to only make a negative number positive then try this:
int answer = Math.abs(x);
A little cool math trick! Squaring the number will guarantee a positive value of x^2, and then, taking the square root will get you to the absolute value of x:
int answer = Math.sqrt(Math.pow(x, 2));
Hope it helps! Good Luck!
This code is not safe to be called on positive numbers.
int x = -20
int y = x + (2*(-1*x));
// Therefore y = -20 + (40) = 20
Are you asking about absolute values?
Math.abs(...) is the function you probably want.
You want to wrap each number into Math.abs(). e.g.
System.out.println(Math.abs(-1));
prints out "1".
If you want to avoid writing the Math.-part, you can include the Math util statically. Just write
import static java.lang.Math.abs;
along with your imports, and you can refer to the abs()-function just by writing
System.out.println(abs(-1));
The easiest, if verbose way to do this is to wrap each number in a Math.abs() call, so you would add:
Math.abs(1) + Math.abs(2) + Math.abs(1) + Math.abs(-1)
with logic changes to reflect how your code is structured. Verbose, perhaps, but it does what you want.
When you need to represent a value without the concept of a loss or absence (negative value), that is called "absolute value".
The logic to obtain the absolute value is very simple: "If it's positive, maintain it. If it's negative, negate it".
What this means is that your logic and code should work like the following:
//If value is negative...
if ( value < 0 ) {
//...negate it (make it a negative negative-value, thus a positive value).
value = negate(value);
}
There are 2 ways you can negate a value:
By, well, negating it's value: value = (-value);
By multiplying it by "100% negative", or "-1": value = value *
(-1);
Both are actually two sides of the same coin. It's just that you usually don't remember that value = (-value); is actually value = 1 * (-value);.
Well, as for how you actually do it in Java, it's very simple, because Java already provides a function for that, in the Math class: value = Math.abs(value);
Yes, doing it without Math.abs() is just a line of code with very simple math, but why make your code look ugly? Just use Java's provided Math.abs() function! They provide it for a reason!
If you absolutely need to skip the function, you can use value = (value < 0) ? (-value) : value;, which is simply a more compact version of the code I mentioned in the logic (3rd) section, using the Ternary operator (? :).
Additionally, there might be situations where you want to always represent loss or absence within a function that might receive both positive and negative values.
Instead of doing some complicated check, you can simply get the absolute value, and negate it: negativeValue = (-Math.abs(value));
With that in mind, and considering a case with a sum of multiple numbers such as yours, it would be a nice idea to implement a function:
int getSumOfAllAbsolutes(int[] values){
int total = 0;
for(int i=0; i<values.lenght; i++){
total += Math.abs(values[i]);
}
return total;
}
Depending on the probability you might need related code again, it might also be a good idea to add them to your own "utils" library, splitting such functions into their core components first, and maintaining the final function simply as a nest of calls to the core components' now-split functions:
int[] makeAllAbsolute(int[] values){
//#TIP: You can also make a reference-based version of this function, so that allocating 'absolutes[]' is not needed, thus optimizing.
int[] absolutes = values.clone();
for(int i=0; i<values.lenght; i++){
absolutes[i] = Math.abs(values[i]);
}
return absolutes;
}
int getSumOfAllValues(int[] values){
int total = 0;
for(int i=0; i<values.lenght; i++){
total += values[i];
}
return total;
}
int getSumOfAllAbsolutes(int[] values){
return getSumOfAllValues(makeAllAbsolute(values));
}
Why don't you multiply that number with -1?
Like This:
//Given x as the number, if x is less than 0, return 0 - x, otherwise return x:
return (x <= 0.0F) ? 0.0F - x : x;
If you're interested in the mechanics of two's complement, here's the absolutely inefficient, but illustrative low-level way this is made:
private static int makeAbsolute(int number){
if(number >=0){
return number;
} else{
return (~number)+1;
}
}
Library function Math.abs() can be used.
Math.abs() returns the absolute value of the argument
if the argument is negative, it returns the negation of the argument.
if the argument is positive, it returns the number as it is.
e.g:
int x=-5;
System.out.println(Math.abs(x));
Output: 5
int y=6;
System.out.println(Math.abs(y));
Output: 6
String s = "-1139627840";
BigInteger bg1 = new BigInteger(s);
System.out.println(bg1.abs());
Alternatively:
int i = -123;
System.out.println(Math.abs(i));
To convert negative number to positive number (this is called absolute value), uses Math.abs(). This Math.abs() method is work like this
“number = (number < 0 ? -number : number);".
In below example, Math.abs(-1) will convert the negative number 1 to positive 1.
example
public static void main(String[] args) {
int total = 1 + 1 + 1 + 1 + (-1);
//output 3
System.out.println("Total : " + total);
int total2 = 1 + 1 + 1 + 1 + Math.abs(-1);
//output 5
System.out.println("Total 2 (absolute value) : " + total2);
}
Output
Total : 3
Total 2 (absolute value) : 5
I would recommend the following solutions:
without lib fun:
value = (value*value)/value
(The above does not actually work.)
with lib fun:
value = Math.abs(value);
I needed the absolute value of a long , and looked deeply into Math.abs and found that if my argument is less than LONG.MIN_VAL which is -9223372036854775808l, then the abs function would not return an absolute value but only the minimum value. Inthis case if your code is using this abs value further then there might be an issue.
Can you please try this one?
public static int toPositive(int number) {
return number & 0x7fffffff;
}
if(arr[i]<0)
Math.abs(arr[i]); //1st way (taking absolute value)
arr[i]=-(arr[i]); //2nd way (taking -ve of -ve no. yields a +ve no.)
arr[i]= ~(arr[i]-1); //3rd way (taking negation)
I see people are saying that Math.abs(number) but this method is not full proof.
This fails when you try to wrap Math.abs(Integer.MIN_VALUE) (see ref. https://youtu.be/IWrpDP-ad7g)
If you are not sure whether you are going to receive the Integer.MIN_VALUE in the input. It is always recommended to check for that number and handle it manually.
In kotlin you can use unaryPlus
input = input.unaryPlus()
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/unary-plus.html
Try this in the for loop:
sum += Math.abs(arr[i])
dont do this
number = (number < 0 ? -number : number);
or
if (number < 0) number = -number;
this will be an bug when you run find bug on your code it will report it as RV_NEGATING_RESULT_OF