Number of bits allocated to 0 is 0 in java- Why? - java

While learning BigInteger.valueOf(0L).bitLength() and BigInteger.valueOf(0L).bitCount() I found it is returning 0
However, the if consider 0 as a number then it should also needs one bit.
From my understanding I expect 1 as return value for both methods instead of 0.
public class Test {
public static void main(String[] args) {
int bitLength = BigInteger.valueOf(0L).bitLength();
int bitCount = BigInteger.valueOf(0L).bitCount();
System.out.println("bitLength=" + bitLength);
System.out.println("bitCount=" + bitCount);
}
}
Please help me understand why It is behaving like this ?

int bitCount()
Returns the number of bits in the two's complement representation of this BigInteger that differ from its sign bit.
For your BigInteger.valueOf(0L) example, the sign bit is 0, and there are no 1 bits, hence 0 is returned (since there are no bits that differ from the sign bit).
int bitLength()
Returns the number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit.
For your BigInteger.valueOf(0L) example, the minimal two's-complement representation of this BigInteger would include just the sign bit 0, so if you exclude the sign bit from the count, as the Javadoc states, you get 0.
It is interesting to note that for the same reasons BigInteger.valueOf(-1L) would also return 0 for both of these methods. Here the sign bit is 1, and after excluding it there are no other bits.

The high-level explanation is that if you have a storage system with a variable number of data bits plus a count, then the count provides some information on the value of the number, so the number of data bits required is less than a system without a count (or with a fixed count).
For normal integer types the "count" is provided by the type information and it is a fixed value. So there is an assumption, for example, that a short is 16 bits, an int is 32 bits, etc. Because of the few possibiities that a size can be (it is not fully variable) the number of bits used even for a zero value is also fixed at that number.
For BigInteger, the bit count is variable and there are various counts you can look at in the source code; some seem redundant, but the unavoidable one is the length of the data array:
final int[] mag;
Setting this array to length zero can represent a zero value, but since you still have the array count, it isn't really using zero bytes.
The bitCount and bitLength values have somewhat arbitrary definitions that don't really relate to the memory utilisation of the class but do have some functional use.
An explanation of the difference between these two methods is given in another question: What is the difference between `bitCount()` and `bitLength()` of a `BigInteger`.

Good reference about difference in both calls - Found here
Official documentation
0 is neither positive nor negative.
BigInteger h = BigInteger.valueOf(0);
System.out.println("h="+ h
+ "[binary=" + h.toString(2) + "]"
+ "[bit count="+ h.bitCount()+ "]"
+ "[bit length=" + h.bitLength() + "]");
h = h.negate();
System.out.println("h="+ h
+ "[binary=" + h.toString(2) + "]"
+ "[bit count="+ h.bitCount()+ "]"
+ "[bit length=" + h.bitLength() + "]");
//Output
//h=0[binary=0][bit count=0][bit length=0]
//h=0[binary=0][bit count=0][bit length=0]
Few samples for positive and negative numbers -
1[binary=1][bit count=1][bit length=1]
-1[binary=-1][bit count=0][bit length=0]
2[binary=10][bit count=1][bit length=2]
-2[binary=-10][bit count=1][bit length=1]
3[binary=11][bit count=2][bit length=2]
-3[binary=-11][bit count=1][bit length=2]
8[binary=1000][bit count=1][bit length=4]
-8[binary=-1000][bit count=3][bit length=3]
10[binary=1010][bit count=2][bit length=4]
-10[binary=-1010][bit count=2][bit length=4]
13[binary=1101][bit count=3][bit length=4]
-13[binary=-1101][bit count=2][bit length=4]
50[binary=110010][bit count=3][bit length=6]
-50[binary=-110010][bit count=3][bit length=6]

Related

Can we assume that x == (int)sqrt(x * x) for all positive integers?

In C++ the sqrt function operates only with double values.
If we use integers (unsigned long long) can we be sure that
x == sqrt(x * x)
for any positive x where x * x <= MAXIMUM_VALUE?
Is it depend on the machine architecture and compiler?
In Java, Math.sqrt(x) takes a double value. You stated that x is such that x * x is below Integer.MAX_VALUE. Every integer is perfectly representable in double - double in java is explicitly defined as an iEEE-754 style double with a 52-bit mantissa; therefore in java a double can perfectly represent all integral values between -2^52 and +2^52, which easily covers all int values (as that is defined as signed 32-bit on java), but it does not cover all long values. (Defined as signed 64-bit; 64 is more than 52, so no go).
Thus, x * x loses no precision when it ends up getting converted from int to double. Then, Math.sqrt() on this number will give a result that is also perfectly representable as a double (because it is x, and given that x*x fits in an int, x must also fit), and thus, yes, this will always work out for all x.
But, hey, why not give it a shot, right?
public static void main(String[] args) {
int i = 1;
while (true) {
if (i * i < 0) break;
int j = (int) Math.sqrt(i * i);
if (i != j) System.out.println("Oh dear! " + i + " -> " + j);
i++;
}
System.out.println("Done at " + i);
}
> Done at 46341
Thus proving it by exhaustively trying it all.
Turns out, none exist - any long value such that x * x still fits (thus, is <2^63-1) has the property that x == (long) Math.sqrt(x * x);. This is presumably because at x*x, the number fits perfectly in a long, even if not all integer numbers that are this large do. Proof:
long p = 2000000000L;
for (; true; p++) {
long pp = p * p;
if (pp < 0) break;
long q = (long) Math.sqrt(pp);
if (q != p) System.out.println("PROBLEM: " + p + " -> " + q);
}
System.out.println("Abort: " + p);
> Abort: 3037000500
Surely if any number exists that doesn't hold, there is at least one in this high end range. Starting from 0 takes very long.
But do we know that sqrt will always return an exact value for a perfect square, or might it be slightly inaccurate?
We should - it's java. Unlike C, almost everything is 'well defined', and a JVM cannot legally call itself one if it fails to produce the exact answer as specified. The leeway that the Math.sqrt docs provide is not sufficient for any answer other than precisely x to be a legal implementation, therefore, yes, this is a guarantee.
In theory the JVM has some very minor leeway with floating point numbers, which strictfp disables, but [A] that's more about using 80-bit registers to represent numbers instead of 64, which cannot possibly ruin this hypothesis, and [B] a while back a java tag question showed up to show strictfp having any effect on any hardware and any VM version and the only viable result was a non-reproducible thing from 15 years ago. I feel quite confident to state that this will always hold, regardless of hardware or VM version.
I think we can believe.
Type casting a floating point number to an integer is to take only integer part of it. I believe you may concern, for example, sqrt(4) yields a floating point number like 1.999...9 and it is type casted to 1. (Yielding 2.000...1 is fine because it will be type casted to 2.)
But the floating number 4 is like
(1 * 2-0 + 0 + 2-1 + ... + 0 * 2-23) * 22
according to Floating-point arithmetic.
Which means, it must not be smaller than 4 like 3.999...9. So also, sqrt of the number must not be smaller than
(1 * 2-0) * 2
So sqrt of a square of an integer will at least yield a floating point number greater than but close enough to the integer.
Just try it. Yes it works in Java, for non-negative numbers. Even works for long contrary to common opinion.
class Code {
public static void main(String[] args) throws Throwable {
for (long x=(long)Math.sqrt(Long.MAX_VALUE);; --x) {
if (!(x == (long)Math.sqrt(x * x))) {
System.err.println("Not true for: "+x);
break;
}
}
System.err.println("Done");
}
}
(The first number that doesn't work is 3037000500L which goes negative when squared.)
Even for longs, the range of testable values is around 2^31 or 2*10^9 so for something this trivial it is reasonable to check every single value. You can even brute force reasonable cryptographic functions for 32-bit values - something more people should realise. Won't work so well for the full 64 bits.
BigInteger - sqrt(since 9)
Use cases requiring tighter constraint over possibilities of overflow can use BigInteger
BigInteger should work for any practical use case.
Still for normal use case, this might not be efficient.
Constraints
BigInteger Limits
BigInteger must support values in the range -2^Integer.MAX_VALUE (exclusive) to +2^Integer.MAX_VALUE (exclusive) and may support values outside of that range. An ArithmeticException is thrown when a BigInteger constructor or method would generate a value outside of the supported range. The range of probable prime values is limited and may be less than the full supported positive range of BigInteger. The range must be at least 1 to 2500000000.
Implementation Note:
In the reference implementation, BigInteger constructors and operations throw ArithmeticException when the result is out of the supported range of -2^Integer.MAX_VALUE (exclusive) to +2^Integer.MAX_VALUE (exclusive).
Array size limit when initialized as byte array
String length limit when initialized as String
Definitely may not support 1/0
jshell> new BigInteger("1").divide(new BigInteger("0"))
| Exception java.lang.ArithmeticException: BigInteger divide by zero
| at MutableBigInteger.divideKnuth (MutableBigInteger.java:1178)
| at BigInteger.divideKnuth (BigInteger.java:2300)
| at BigInteger.divide (BigInteger.java:2281)
| at (#1:1)
An example code
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
public class SquareAndSqrt {
static void valid() {
List<String> values = Arrays.asList("1", "9223372036854775807",
"92233720368547758079223372036854775807",
new BigInteger("2").pow(Short.MAX_VALUE - 1).toString());
for (String input : values) {
final BigInteger value = new BigInteger(input);
final BigInteger square = value.multiply(value);
final BigInteger sqrt = square.sqrt();
System.out.println("value: " + input + System.lineSeparator()
+ ", square: " + square + System.lineSeparator()
+ ", sqrt: " + sqrt + System.lineSeparator()
+ ", " + value.equals(sqrt));
System.out.println(System.lineSeparator().repeat(2)); // pre java 11 - System.out.println(new String(new char[2]).replace("\0", System.lineSeparator()));
}
}
static void mayBeInValid() {
try {
new BigInteger("2").pow(Integer.MAX_VALUE);
} catch (ArithmeticException e) {
System.out.print("value: 2^Integer.MAX_VALUE, Exception: " + e);
System.out.println(System.lineSeparator().repeat(2));
}
}
public static void main(String[] args) {
valid();
mayBeInValid();
}
}
in cmath library sqrt function always convert argument to double or float so the range of double or float much more than unsigned long long so it always give positive.
for reference you can use
https://learn.microsoft.com/en-us/cpp/standard-library/cmath?view=msvc-170,
https://learn.microsoft.com/en-us/cpp/c-language/type-float?view=msvc-170

Explanation about a result

Hi i hav a little problem about some code that i can't give an explanation about the result i have.
//what happens?
public static void what() {
int number = 2147483647;
System.out.println(number + 33);
}
//Here is my solution for the probleme
public static void what() {
long number = 2147483647;
System.out.println(number + 33);
}
The first code with the int number as variable gives me -2147483616 as result. So when i change the int to long i get the good result expected. So question is who can help me give and explanation of why int number + 33 = -2147483616
Java integers are based on 32 Bits. The first bit is kept for the sign (+ = 0 / - = 1).
So 2147483647 equals 01111111 11111111 11111111 11111111.
Adding more will force the value to turn to negative because the first bit is turned into a 1.
10000000 00000000 00000000 00000000 equals -2147483648.
The remaining 32 you are adding to -2147483648 brings you to your result of -2147483616.
The primitive int type has a maximum value of 2147483647, which is what you are setting number to. When anything is added to this value the int type cannot represent it correctly and 'wraps' around, becoming a negative number.
The maximum value of the long type is 9223372036854775807 so the second code snippet works fine because long can hold that value with no problem.
You have reached the maximum of the primitive type int (2147483647).
If int overflows, it goes back to the minimum value (-2147483648) and continues from there.
Consider the calculation of the second snippet, and what the result actually means.
long number = 2147483647;
number += 33;
The result in decimal is 2147483680, in hexadecimal (which more easily shows what the value means) it is 0x80000020.
For the first snippet, the result in hexacimal is also 0x80000020, because the result of arithmetic with the int type is the low 32 bits of the "full" result. What's different is the interpretation: as an int, 0x80000020 has the top bit set, and the top bit has a "weight" of -231, so this result is interpreted as -231 + 32 (a negative number). As a long, the 32nd bit is just a normal bit with a weight of 231 and the result is interpreted as 231 + 32.
The primitive type int is a 32-bit integer that can only store from -2^31 to 2^31 - 1 whereas long is a 64-bit integer so it can obviously store a much larger value.
When we calculate the capacity of int, it goes from -2147483648 to 2147483647.
Now you are wondering.. why is it that when the number exceeds the limit and I add 33 to it, it will become -2147483616?
This is because the data sort of "reset" after exceeding its limit.
Thus, 2147483647 + 1 will lead to -2147483648. From here, you can see that -2147483648 + 32 will lead to the value in your example which is -2147483616.
Some extra info below:
Unless you really need to use a number that is greater than the capacity of int, always use int as it takes up less memory space.
Also, should your number be bigger than long, consider using BigInteger.
Hope this helps!

Bitwise op unexpectedly goes negative

Can someone please explain to me why I'm getting these results?
public static int ipv4ToInt(String address) {
int result = 0;
// iterate over each octet
for(String part : address.split(Pattern.quote("."))) {
// shift the previously parsed bits over by 1 byte
result = result << 8;
System.out.printf("shift = %d\n", result);
// set the low order bits to the current octet
result |= Integer.parseInt(part);
System.out.printf("result = %d\n", result);
}
return result;
}
For ipv4ToInt("10.35.41.134"), I get:
shift = 0
result = 10
shift = 2560
result = 2595
shift = 664320
result = 664361
shift = 170076416
result = 170076550
10.35.41.134 = 170076550
This is the same result that I get when I do the math myself.
For ipv4ToInt("192.168.0.1"), I get:
shift = 0
result = 192
shift = 49152
result = 49320
shift = 12625920
result = 12625920
shift = -1062731776
result = -1062731775
192.168.0.1 = -1062731775
For this one, when I do the math manually, I get 3232235521.
Interestingly:
3232235521 = 11000000101010000000000000000001
And when I enter 1062731775 into my Windows calc and hit the +/- button, I get:
-1062731775 = 11111111111111111111111111111111 11000000101010000000000000000001
The function still works for my purposes, but I'm just really curious to know why on earth result is going negative when I do that last bit shift?
Because of bit overflow in your case!
In Java, the integer is also 32 bits and range is from -2,147,483,648 to 2,147,483,647.
12625920 << 8 crosses the limit of 2^31-1 and hence,the result turns negative...
The result just overturns from -ve side and hence,whatever range is left from the positive side is accompanied by that much from negative side!!!
As suggested by everyone,you should use long variable to avoid overflow!
All primitives in java are signed - They can be positive or negative. The highest bit is used to control this, so when it gets set, the number becomes negative.
Try using a long instead - that will give you the wanted result, as longs can be much larger without overflow being hit.
11000000101010000000000000000001 is 32 bits. The value it represents depends on how you interpret those bits:
as a 32bit signed integer, it is negative (because the left-most bit is 1)
as a 32bit unsigned integer, it is positive (like every other unsigned integer)
as the lowers bits of a long (signed or unsigned), it would give a positive value (if the left-most bits stay 0)
Java uses signed integers, so if you print the value, you'll see a negative number. That does not mean your bits are wrong.
It matters only for printing, you can use these ways for printing a positive integer:
1) change result to long (java will do the work for you).
2) handle signed int as unsigned int by yourself (possibly make a method int2string(int n) or toString(int n).
3) Integer.toUnsignedString(int) is you are using java 8.
As far as I understand, your are parsing an IP address, remember, java use signed data types, you can't have a 32 bits integer.
change result to long to fix that.

Impose numerical limit using mathematics

I want to return a number that doesn't exceed a limit I set. For example I want to do the equivalent of:
if (number >= limit)
number = limit;
return number;
Is there a mathematical way of doing the equivalent of what I just described in just one line?
You could:
return Math.min(number, limit);
or:
return number >= limit ? limit : number;
There's also the following mathematical formula: (taken from here)
min(a,b) = 1/2 (a + b - |a - b|)
Code:
return ( number + limit - Math.abs(number - limit) ) / 2;
Now Math.abs looks pretty similar to Math.min (so there wouldn't be much point to using the above instead of simply Math.min), although you could easily replace that with the method presented here or here:
mask = n >> 31 // 11111111 for negative and 00000000 for positive
abs = (mask + n)^mask // convert negative to positive in 2's complement
// while not changing positive
Note:
If number + limit can overflow, this won't work. This can be changed to
number - Math.abs(...) + limit to avoid this, but then number - Math.abs(...) can still underflow - you just need to keep overflow in mind and select the option that would prevent over/underflow based on the range of the numbers, or go for the non-arithmetic option.
Also keep in mind that, assuming no over/underflow, if you're dealing with floating point values (float / double) rather than integral types, the result of the above won't necessarily return either of the values (because of the way floating point representation works).

How Java processes for overflow integers [duplicate]

This question already has answers here:
Why do these two multiplication operations give different results?
(2 answers)
Closed 9 years ago.
Now signed_int max value is 2,147,483,647 i.e. 2^31 and 1 bit is sign bit, so
when I run long a = 2,147,483,647 + 1;
It gives a = -2,147,483,648 as answer.. This hold good.
But, 24*60*60*1000*1000 = 86400000000 (actually)...
In java, 24*60*60*1000*1000 it equals to 500654080..
I understand that it is because of overflow in integer, but what processing made this value come, What logic was used to get that number by Java. I also refered here.
Multiplication is executed from left to right like this
int x = 24 * 60;
x = x * 60;
x = x * 1000;
x = x * 1000;
first 3 operations produce 86400000 which still fits into Integer.MAX_VALUE. But the last operation produces 86400000000 which is 0x141dd76000 in hex. Bytes above 4 are truncated and we get 0x1dd76000. If we print it
System.out.println(0x1dd76000);
the result will be
500654080
This is quite subtle: when writing long a = 2147483647 + 1, the right hand side is computed first using ints since you have supplied int literals. But that will clock round to a negative (due to overflow) before being converted to a long. So the promotion from int to long is too late for you.
To circumvent this behaviour, you need to promote at least one of the arguments to a long literal by suffixing an L.
This applies to all arithmetic operations using literals (i.e. also your multiplication): you need to promote one of them to a long type.
The fact that your multiplication answer is 500654080 can be seen by looking at
long n = 24L*60*60*1000*1000;
long m = n % 4294967296L; /* % is extracting the int part so m is 500654080
n.b. 4294967296L is 2^32 (using OP notation, not XOR). */
What's happening here is that you are going 'round and round the clock' with the int type. Yes, you are losing the carry bits but that doesn't matter with multiplication.
As the range of int is -2,147,483,648 to 2,147,483,647.
So, when you keep on adding numbers and its exceed the maximum limit it start gain from the left most number i.e. -2,147,483,648, as it works as a cycle. That you had already mentioned in your question.
Similarly when you are computing 24*60*60*1000*1000 which should result 86400000000 as per Maths.
But actually what happens is somehow as follows:
86400000000 can be written as 2147483647+2147483647+2147483647+2147483647+..36 times+500654080
So, after adding 2147483647 for 40 times results 0 and then 500654080 is left which ultimately results in 500654080.
I hope its clear to you.
Add L in your multiplicatoin. If you add L than it multiply you in Long range otherwise in Integer range which overflow. Try to multiply like this.
24L*60*60*1000*1000
This give you a right answer.
An Integer is 32 bit long. Lets take for example a number that is 4 bit long for the sake of simplicity.
It's max positive value would be:
0111 = 7 (first bit is for sign; 0 means positive, 1 means negative)
0000 = 0
It's min negative value would be:
1111 = -8 (first bit is for sign)
1000 = -1
Now, if we call this type fbit, fbit_max is equal to 7.
fbit_max + 1 = -8
because bitwise 0111 + 1 = 1111
Therefore, the span of fbit_min to fbit_max is 16. From -8 to 7.
If you would multiply something like 7*10 and store it in fbit, the result would be:
fbit number = 7 * 10 (actually 70)
fbit number = 7 (to get to from zero to max) + 16 (min to max) + 16 (min to max) + 16 (min to max) + 15 (the rest)
fbit number = 6
24*60*60*1000*1000 = 86400000000
Using MOD as follows: 86400000000 % 2147483648 = 500654080

Categories