I don't understand what is this doCalculatePi means or does, in the following example:
public static double doCalculatePi(final int sliceNr) {
final int from = sliceNr * 10;
final int to = from + 10;
final int c = (to << 1) + 1;
double acc = 0;
for (int a = 4 - ((from & 1) << 3), b = (from << 1) + 1; b < c; a = -a, b += 2) {
acc += ((double) a) / b;
}
return acc;
}
public static void main(String args[]){
System.out.println(doCalculatePi(1));
System.out.println(doCalculatePi(2));
System.out.println(doCalculatePi(3));
System.out.println(doCalculatePi(4));
System.out.println(doCalculatePi(10));
System.out.println(doCalculatePi(100));
}
I have printed the values to understand what the results are but I still have no clue what this code calculates. The conditions inside the loop are not clear.
<< means left shift operation, which shifts the left-hand operand left by the number of bits specified by the right-hand operand (See oracle docs).
Say, you have a decimal value, 5 which binary representation is 101
Now for simplicity, consider,
byte a = (byte)0x05;
Hence, the bit representation of a will be,
a = 00000101 // 1 byte is 8 bit
Now if you left shift a by 2, then a will be
a << 2
a = 00010100 //shifted place filled with zero/s
So, you may now understand that, left shift a by 3 means
a << 3
a = 00101000
For better understanding you need to study Bitwise operation.
Note, you are using int instead of byte, and by default, the int data type is a 32-bit signed integer (reference here), so you have to consider,
int a = 5;
in binary
a << 3
a = 00000000 00000000 00000000 00101000 // total 32 bit
My guess is that it approximates PI with
PI = doCalculatePi(0)+doCalculatePi(1)+doCalculatePi(2)+...
Just a guess.
Trying this
double d = 0;
for(int k = 0; k<1000; k++) {
System.out.println(d += doCalculatePi(k));
}
gives me
3.0418396189294032
3.09162380666784
3.1082685666989476
[...]
3.1414924531892394
3.14149255348994
3.1414926535900394
<< is the Bitshift operator.
Basically, every number is represented as a series of binary digits (0's and 1's), and you're shifting each of those digits to the left by however many places you indicate. So for example, 15 is 00001111 and 15 << 1 is 00011110 (or 30), while 15 << 2 is (00111100) which is 60.
There's some special handling that comes into play when you get to the sign bit, but you should get the point.
Related
Given an array filled with 4 bytes inside (R,G,B,A), I'm trying to translate this array full of 4 8bits numbers into its translation in 32bits. To be more clear, if I get an array such as:
byte[] tab = {1,2,3,4};
with translated in binary in 8bit :
1 = 0b00000001
2 = 0b00000010
3 = 0b00000011
4 = 0b00000100
Then, my method should return a byte array such as :
newTab = {00000001_00000010_00000011_00000100};
For some reason, I'm trying to do this without using a String to concatenate the bytes.
I've already tried something with binary operators such as <<, >> or |, but without success...
So far, my code looks like this :
byte[] tab = {1,2,3,4};
int tmp,tabToInt = 0;
for (int x = 0 ; x < tab.length ; ++x){
tmp = tmp << (tab.length - 1 - x)*8;
byteToInt = byteToInt | tmp;
}
return tabToInt;
But it didn't seem to work, even less with negatives bytes... (like -1 = 0b11111111)
Thanks in advance for your answers!
You can use ByteBuffer like this.
byte[] tab = {1, 2, 3, 4};
int tabToInt = ByteBuffer.wrap(tab).getInt();
System.out.println("decimal = " + tabToInt);
System.out.println("binary = " + Integer.toBinaryString(tabToInt));
System.out.println("hexadecimal =" + Integer.toHexString(tabToInt));
output
decimal = 16909060
binary = 1000000100000001100000100
hexadecimal =1020304
ByteBuffer can do it, but only if you get passed at least 4 bytes.
The problem with your code is two-fold:
I think you typoed somewhere, your code doesn't even compile. I think you meant tmp = tab[x] << (tab.length - 1 - x)*8;. Your snippet never does anything with tab other than ask for its length.
Negative numbers extend, and java will convert any byte or short to an int the moment you do any math to it. So, 0b1111 1111, if you try to do e.g. << 8 on that, java first turns that -1 byte into a -1 int (so that's now 32 1 bits), and then dutifully left shifts it by 8, so now that's 24 1 bits, followed by 8 0 bits. You then bitwise OR that into your target, and thus now the target is mostly 1 bits. To convert a byte to an int without "sign extension", (b & 0xFF does it:
byte b = (byte) 0b1111_1111;
assert b == -1; // yup, it is
int c = b; // legal
assert c == -1; // yeah, still is. uhoh. That's...
int d = 0b11111111_11111111_11111111_11111111;
assert c == d; // yeah. We don't want that.
int e = (b & 0xFF);
assert e = 255;
int f = 0b0000000_0000000_0000000_11111111;
assert e == f; // yes!
It's been a while, that I did bit manipulations and I'm not sure if this can be done in a more effective way.
What I want is to get bits of a specific range from a value.
Let's say the binary of the value is: 0b1101101
Now I want to get a 4-bit range from the 2nd to the 5th bit of this value in it's two's complement.
The range I wanna get: 0b1011
Value in Two's complement: -5
This is the code I have, with some thoughts what I'm doing:
public int bitRange(int value, int from, int to) {
// cut the least significant bits
value = value >> from;
// create the mask
int mask = 0;
for (int i = from; i <= to; i++) {
mask = (mask << 1) + 1;
}
// extract the bits
value = value & mask;
// needed to check the MSB of the range
int msb = 1 << (to - from);
// if MSB is 1, XOR and inverse it
if ((value & msb) == msb ) {
value = value ^ mask;
value = ~value;
}
return value;
}
Now I would like to know if this can be done more effective? Especially the creation of the dynamic mask and the check of the MSB of the range, to be able to convert the bit range. Another point is, as user3344003 pointed out correctly, if the range would be 1 bit, the output would be -1. I'm sure there is a possible improvement.
For your mask, you could go something like
int mask = 0xffffffff >> 32-(to-from);
Though the chance of that exact code being correct is small. Probably off by one, edge issues, sign problems. But it's on the right track?
Here's your mask:
int mask = 0xffffffff >>> 32 - (to - from + 1);
You have to use >>> due to sign bit is 1.
Another solution could be to store the possible masks which can be 31 values at the most:
private static int[] MASKS = new int[31];
static {
MASKS[0] = 1;
for (int i = 1; i < MASKS.length; i++)
MASKS[i] = (MASKS[i - 1] << 1) + 1;
}
And using this your mask:
int mask = MASKS[to - from];
You can do the same for the msb mask, just store the possible values in a static array, and you don't have to calculate it in your method.
Disclaimer: I'm more of a C or C++ programmer, and I know there are some subtles between the bitwise operators in the different languages. But it seems to me that this can be done in one line as follows by taking advantage of the arithmetic shift that will result when shifting a negative value to the right, where one's will be shifted in for the sign extension.
public int bitRange(int value, int from, int to) {
int waste = 31 - to;
return (value << waste) >> (waste + from);
}
breakdown:
int a = 31 - to; // the number of bits to throw away on the left
int b = value << a; // shift the bits to throw away off the left of the value
int c = a + from; // the number of bits that now need to be thrown away on the right
int d = b >> c; // throw bits away on the right, and extend the sign on the left
return d;
The task is to read an integer from keyboard, convert it into 8 groups of 4 bits, then convert each bit into a hex number and output them one after one. This must be done by using bit shifting, no other solution counts.
My idea was to use a mask with 4 ones to select the group of bits, then shift that group right, removing preceding zeroes, and output the number in hex.
Here's how I tried to approach this:
public static void main(String args[]) {
Scanner input = new Scanner(System.in);
System.out.print("Enter an integer: ");
int x = input.nextInt();
System.out.println("Binary representation: " + Integer.toBinaryString(x));
System.out.println("Hexadecimal representatio1n: " + Integer.toHexString(x));
int mask = 15 << 28;
System.out.println(Integer.toBinaryString(mask));
int k = 28;
for (int i = 1; i <= 8; i++)
{
int result = mask & x;
//System.out.println(Integer.toBinaryString(result));
result = x >>> k ;
mask = mask >> 4;
k = k - 4;
System.out.println(Integer.toHexString(result));
}
}
Sample output:
Enter an integer: 324234234
Binary representation: 10011010100110110101111111010
Hexadecimal representatio1n: 13536bfa
11110000000000000000000000000000
1
13
135
1353
13536
13536b
13536bf
13536bfa
Why is it not working correctly?
Thanks.
Your when you shift the result variable, you aren't shifting by the result, you are shifting it by x
if you change it to
result = result >>> k;
it should work
on a side note, this problem is much easier done the other way(from the least significant bit to the most significant bit)
like
int x = 0xaabcdabcd;
int mask = 0x0fffffff;
for(int i =0;i < 8; i ++){
System.out.println(x & mask);
x = x >>> 4;
}
Because there are no unsigned types in Java, on line int mask = 15 << 28; you practically make your mask negative by moving bits up to sign field. Later you move it left with mask = mask >> 4; and thus carry down the sign bit. After the shift, your mask is not 00001111000000000000000000000000 but 11111111000000000000000000000000. Use logical right shift operator >>> instead.
PS. This seems like a homework. In such cases, one who asks question should mark the question with homework tag.
Java's Random function takes a seed and produces the a sequence of 'psuedo-random' numbers.
(It is implemented based on some algorithm discussed in Donald Knuth, The Art of Computer Programming, Volume 3, Section 3.2.1.), but the article is too technical for me to understand)
Is there an inverse function of it?
That is, given a sequence of numbers, would it be possible to mathematically determine what the seed would be?
(, which means, brute-forcing doesn't count as a valid method)
[Edit]
There seems to be quite a number of comments here... I thought I'd clarify what I am looking for.
So for instance, the function y = f(x) = 3x has an inverse function, which is y = g(x) = x/3.
But the function z = f(x, y) = x * y does not have an inverse function, because (I could give a full mathematical proof here, but I don't want to sidetrack my main question), intuitively speaking, there are more than one pair of (x, y) such that (x * y) == z.
Now back to my question, if you say the function is not inversible, please explain why.
(And I am hoping to get answers from those who have really read to article and understand it. Answers like "It's just not possible" aren't really helping)
If we're talking about the Oracle (née Sun) implementation of java.util.Random, then yes, it is possible once you know enough bits.
Random uses a 48-bit seed and a linear congruential generator. These are not cryptographically safe generators, because of the tiny state size (bruteforceable!) and the fact that the output just isn't that random (many generators will exhibit small cycle length in certain bits, meaning that those bits can be easily predicted even if the other bits seem random).
Random's seed update is as follows:
nextseed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)
This is a very simple function, and it can be inverted if you know all the bits of the seed by calculating
seed = ((nextseed - 0xBL) * 0xdfe05bcb1365L) & ((1L << 48) - 1)
since 0x5DEECE66DL * 0xdfe05bcb1365L = 1 mod 248. With this, a single seed value at any point in time suffices to recover all past and future seeds.
Random has no functions that reveal the whole seed, though, so we'll have to be a bit clever.
Now, obviously, with a 48-bit seed, you have to observe at least 48 bits of output or you clearly don't have an injective (and thus invertible) function to work with. We're in luck: nextLong returns ((long)(next(32)) << 32) + next(32);, so it produces 64 bits of output (more than we need). Indeed, we could probably make do with nextDouble (which produces 53 bits), or just repeated calls of any other function. Note that these functions cannot output more than 248 unique values because of the seed's limited size (hence, for example, there are 264-248 longs that nextLong will never produce).
Let's specifically look at nextLong. It returns a number (a << 32) + b where a and b are both 32-bit quantities. Let s be the seed before nextLong is called. Then, let t = s * 0x5DEECE66DL + 0xBL, so that a is the high 32 bits of t, and let u = t * 0x5DEECE66DL + 0xBL so that b is the high 32 bits of u. Let c and d be the low 16 bits of t and u respectively.
Note that since c and d are 16-bit quantities, we can just bruteforce them (since we only need one) and be done with it. That's pretty cheap, since 216 is only 65536 -- tiny for a computer. But let's be a bit more clever and see if there's a faster way.
We have (b << 16) + d = ((a << 16) + c) * 0x5DEECE66DL + 11. Thus, doing some algebra, we obtain (b << 16) - 11 - (a << 16)*0x5DEECE66DL = c*0x5DEECE66DL - d, mod 248. Since c and d are both 16-bit quantities, c*0x5DEECE66DL has at most 51 bits. This usefully means that
(b << 16) - 11 - (a << 16)*0x5DEECE66DL + (k<<48)
is equal to c*0x5DEECE66DL - d for some k at most 6. (There are more sophisticated ways to compute c and d, but because the bound on k is so tiny, it's easier to just bruteforce).
We can just test all the possible values for k until we get a value whos negated remainder mod 0x5DEECE66DL is 16 bits (mod 248 again), so that we recover the lower 16 bits of both t and u. At that point, we have a full seed, so we can either find future seeds using the first equation, or past seeds using the second equation.
Code demonstrating the approach:
import java.util.Random;
public class randhack {
public static long calcSeed(long nextLong) {
final long x = 0x5DEECE66DL;
final long xinv = 0xdfe05bcb1365L;
final long y = 0xBL;
final long mask = ((1L << 48)-1);
long a = nextLong >>> 32;
long b = nextLong & ((1L<<32)-1);
if((b & 0x80000000) != 0)
a++; // b had a sign bit, so we need to restore a
long q = ((b << 16) - y - (a << 16)*x) & mask;
for(long k=0; k<=5; k++) {
long rem = (x - (q + (k<<48))) % x;
long d = (rem + x)%x; // force positive
if(d < 65536) {
long c = ((q + d) * xinv) & mask;
if(c < 65536) {
return ((((a << 16) + c) - y) * xinv) & mask;
}
}
}
throw new RuntimeException("Failed!!");
}
public static void main(String[] args) {
Random r = new Random();
long next = r.nextLong();
System.out.println("Next long value: " + next);
long seed = calcSeed(next);
System.out.println("Seed " + seed);
// setSeed mangles the input, so demangle it here to get the right output
Random r2 = new Random((seed ^ 0x5DEECE66DL) & ((1L << 48)-1));
System.out.println("Next long value from seed: " + r2.nextLong());
}
}
I normally wouldn't just link articles... But I found a site where someone looks into this in some depth and thought it was worth posting. http://jazzy.id.au/default/2010/09/20/cracking_random_number_generators_part_1.html
It seems that you can calculate a seed this way:
seed = (seed * multiplier + addend) mod (2 ^ precision)
where multiplier is 25214903917, addend is 11, and precision is 48 (bits). You can't calculate what the seed was with only 1 number, but you can with 2.
EDIT: As nhahtdh said there's a part 2 where he delves into more of the math behind the seeds.
I would like to present an implementation to reverse a sequence of integers generated by nextInt().
The program will brute force on the lower 16-bit discarded by nextInt(), use the algorithm provided in the blog by James Roper to find previous seed, then check that upper 32 bit of the 48-bit seed are the same as the previous number. We need at least 2 integers to derive the previous seed. Otherwise, there will be 216 possibilities for the previous seed, and all of them are equally valid until we have at least one more number.
It can be extended for nextLong() easily, and 1 long number is enough to find the seed, since we have 2 pieces of upper 32-bit of the seed in one long, due to the way it is generated.
Note that there are cases where the result is not the same as what you set as secret seed in the SEED variable. If the number you set as secret seed occupies more than 48-bit (which is the number of bits used for generating random numbers internally), then the upper 16 bits of 64 bit of long will be removed in the setSeed() method. In such cases, the result returned will not be the same as what you have set initially, it is likely that the lower 48-bit will be the same.
I would like to give most the credit to James Roper, the author of this blog article which makes the sample code below possible:
import java.util.Random;
import java.util.Arrays;
class TestRandomReverse {
// The secret seed that we want to find
private static long SEED = 782634283105L;
// Number of random numbers to be generated
private static int NUM_GEN = 5;
private static int[] genNum(long seed) {
Random rand = new Random(seed);
int arr[] = new int[NUM_GEN];
for (int i = 0; i < arr.length; i++) {
arr[i] = rand.nextInt();
}
return arr;
}
public static void main(String args[]) {
int arr[] = genNum(SEED);
System.out.println(Arrays.toString(arr));
Long result = reverse(arr);
if (result != null) {
System.out.println(Arrays.toString(genNum(result)));
} else {
System.out.println("Seed not found");
}
}
private static long combine(int rand, int suffix) {
return (unsignedIntToLong(rand) << 16) | (suffix & ((1L << 16) - 1));
}
private static long unsignedIntToLong(int num) {
return num & ((1L << 32) - 1);
}
// This function finds the seed of a sequence of integer,
// generated by nextInt()
// Can be easily modified to find the seed of a sequence
// of long, generated by nextLong()
private static Long reverse(int arr[]) {
// Need at least 2 numbers.
assert (arr.length > 1);
int end = arr.length - 1;
// Brute force lower 16 bits, then compare
// upper 32 bit of the previous seed generated
// to the previous number.
for (int i = 0; i < (1 << 16); i++) {
long candidateSeed = combine(arr[end], i);
long previousSeed = getPreviousSeed(candidateSeed);
if ((previousSeed >>> 16) == unsignedIntToLong(arr[end - 1])) {
System.out.println("Testing seed: " +
previousSeed + " --> " + candidateSeed);
for (int j = end - 1; j >= 0; j--) {
candidateSeed = previousSeed;
previousSeed = getPreviousSeed(candidateSeed);
if (j > 0 &&
(previousSeed >>> 16) == unsignedIntToLong(arr[j - 1])) {
System.out.println("Verifying: " +
previousSeed + " --> " + candidateSeed);
} else if (j == 0) {
// The XOR is done when the seed is set, need to reverse it
System.out.println("Seed found: " + (previousSeed ^ MULTIPLIER));
return previousSeed ^ MULTIPLIER;
} else {
System.out.println("Failed");
break;
}
}
}
}
return null;
}
private static long ADDEND = 0xBL;
private static long MULTIPLIER = 0x5DEECE66DL;
// Credit to James Roper
// http://jazzy.id.au/default/2010/09/21/cracking_random_number_generators_part_2.html
private static long getPreviousSeed(long currentSeed) {
long seed = currentSeed;
// reverse the addend from the seed
seed -= ADDEND; // reverse the addend
long result = 0;
// iterate through the seeds bits
for (int i = 0; i < 48; i++)
{
long mask = 1L << i;
// find the next bit
long bit = seed & mask;
// add it to the result
result |= bit;
if (bit == mask)
{
// if the bit was 1, subtract its effects from the seed
seed -= MULTIPLIER << i;
}
}
return result & ((1L << 48) - 1);
}
}
I want to know which value the first bit of a byte has.
For example:
I have byte m = (byte) 0x8C;
How could I know if the first bit is an 1 or a 0 ?
Can anyone help me out ?
It depends what you mean by "first bit". If you mean "most significant bit" you can use:
// 0 or 1
int msb = (m & 0xff) >> 7;
Or if you don't mind the values being 0x80 or 0, just use:
// 0 or 0x80
int msb = m & 0x80;
Or in fact, as a boolean:
// Uses the fact that byte is signed using 2s complement
// True or false
boolean msb = m < 0;
If you mean the least significant bit, you can just use:
// 0 or 1
int lsb = m & 1;
If the first bit is the lowest bit (ie bit 0), then
if((m & 1) >0) ...
should do it.
In general,
if ((m & (1<<N)) > 0) ...
will give you whether or not bit N is set.
If, however, you meant the highest bit (bit 7), then use N=7.
Assuming you mean leftmost bit, bitwise and it with 0x80 and check if it is zero nor not:
public boolean isFirstBitSet(byte b) {
System.out.println((b & (byte)0x80));
return (b & (byte)0x80) < 0;
}
If you mean lowest order bit you will need to and with 0x01 and check a different condition:
public boolean isFirstBitSet(byte b) {
System.out.println((b & (byte)0x01));
return (b & (byte)0x80) > 0;
}
Use the bitwise and operator.
public class BitExample {
public static void main(String args[]) throws Exception {
byte m = (byte)0x8C;
System.out.println("The first bit is " + (m & (byte)0x01));
m = (byte)0xFF;
System.out.println("The first bit is " + (m & (byte)0x01));
}
}
// output is...
The first bit is 0
The first bit is 1
Its a bit of a hack but you can use
if(x >> -1 != 0) // top bit set.
This works for byte, short, int, long data types.
However for most types the simplest approach is to compare with 0
if (x < 0) // top bit set.
This works for byte, short, int, long, float, or double
(Ignoring negative zero and negative NaN, most people do ;)
For char type you need to know the number of bits. ;)
if (ch >>> 15 != 0) // top bit set.
This code gives you msb(most significant bit)/biggest number which is a
power of 2 and less than any given number.
class msb{
void main(){
int n=155;//let 110001010
int l=(Integer.toBinaryString(n)).length();//9
String w="0"+Integer.toBinaryString(i).substring(1);//010001010
i=Integer.parseInt(w,2);
System.out.println(n^i);//110001010^010001010=100000000
}
}