0

For example if I do:

  let sieve = new Uint32Array(1).fill(1);

I would like to look at the bit pattern at index 0 which should be

0000000000000000000000000001

I want to print it out to the console so that I get something like this:

0 0
1 0
2 0
3 0
.
.
.
31 1

Can I simply shift right to grab the 1 using >> or do I have to use a bitwise AND as & as well?

As a side, does it effect things if you switch to a signed representation such as here ...

Int32Array

jennifer
  • 682
  • 5
  • 14
  • Your text and your code suggest slightly different things... You're setting the value to 1, you already know it's 1, why do you need to check the first bit? If that's just for illustrative purposes though, don't pick 1, pick some large random odd number =) And then if you have "some random value on it", bitmasking is the way to go if you need to check several bits from the same value (using the standard `if (val & mask === mask)`) – Mike 'Pomax' Kamermans Feb 19 '20 at 15:53

2 Answers2

1

There is nothing special to do that relates to Uint32Array... You can just deal with sieve[0] as you would with any integer number:

let sieve = new Uint32Array(1).fill(1);

console.log(
    Array.from(sieve[0].toString(2).padStart(32, 0), (bit, i) => `${i} ${bit}`)
         .join("\n")
);
trincot
  • 317,000
  • 35
  • 244
  • 286
  • That's... a very expensive way to check a single bit value O_o – Mike 'Pomax' Kamermans Feb 19 '20 at 15:54
  • @Mike'Pomax'Kamermans, OP wrote "I want to print it out to the console so that I get something like this". This does *exactly* that. – trincot Feb 19 '20 at 15:55
  • Yes but then they show it printed bit for bit, not the zero padded string, in which case successive shifts make sense. – Mike 'Pomax' Kamermans Feb 19 '20 at 15:56
  • OP's question only differs in which side the bits are counted from. Using stringification and padding is really inefficient indeed. – Aurel Bílý Feb 19 '20 at 15:56
  • @AurelBílý, what do you mean with "only differs"? Compared to what? – trincot Feb 19 '20 at 15:57
  • @trincot Actually never mind; you are not using the result of the "full" binary form anyway, so why base all the calculations on it? – Aurel Bílý Feb 19 '20 at 15:58
  • @AurelBílý, full binary form? calculations? I have no idea what you are trying to say... – trincot Feb 19 '20 at 15:59
  • @trincot The `sieve[0].toString(2).padStart(32, 0)` part. It is just rather inefficient to do basic binary arithmetic by converting the number to a string and looking at the literal characters. – Aurel Bílý Feb 19 '20 at 16:01
  • Why would you care about a microsecond of efficiency when the OP explicitly wants to "print out to console" -- which includes stringification anyhow (!!), and is the most inefficient part of the whole process? – trincot Feb 19 '20 at 16:03
  • Just realise what the performance impact is to call `console.log` 32 times, and in each call two numbers are converted to string by the console API... On the contrary to what you say here, I actually think it is beneficial to create one final string first, and then call `console.log` only once. – trincot Feb 19 '20 at 16:10
  • jsperf agrees with you: the initial string, then print, performs better in both FF and Chrome than successive bit shifting, even if the code looks like it'd be slower. – Mike 'Pomax' Kamermans Feb 19 '20 at 16:13
  • Interesting; anyhow, I think performance considerations should be relative to the use of `console.log`. Once you use that, gaining a microsecond cannot be important. Also, measuring the impact of `console.log` is not always correct, since the console has parts that run asynchronously, and would escape the time measurements. – trincot Feb 19 '20 at 16:18
  • I know performance doesn't matter for such a small example. It seemed to me a little bit of an indirect solution to get bits out of a number. But for the record, using actual arithmetic is faster (as expected), when the `console.log` bottleneck is removed: [jsperf](https://jsperf.com/binary-by-tostring-or-arithmetic/1). (: – Aurel Bílý Feb 19 '20 at 18:36
1

This is just a number to binary conversion.

let arr = new Uint32Array(1).fill(1);
for (let i = 0; i < 32; i++) {
  console.log(i, (arr[0] >>> i) & 1);
}

As it is, the fact that the number comes from Uint32Array makes no difference, but maybe this is because you simplified your question.

Also note that the "ones" bit, which you want in your question to be printed as 31, is in fact the first bit, because bits are counted starting from zero on the right (the least significant bit). If you really wanted to count it the non-standard way as in the question, then:

let arr = new Uint32Array(1).fill(1);
for (let i = 0; i < 32; i++) {
  console.log(i, (arr[0] >>> (31 - i)) & 1);
}

Edit: for the values to be correct even when the MSB is set (the "sign bit"), unsigned bit shifting (>>>) has to be used.

Aurel Bílý
  • 7,068
  • 1
  • 21
  • 34
  • Unit32Array creates an us-signed as opposed to a signed representation meaning all 32 bit are the value and no sign bit is needed. Curious as to why this does not effect the result? – jennifer Feb 19 '20 at 16:19
  • @j.a. That's a good point, and I corrected my answer (you need to use `>>>`). But the fact that it doesn't matter whether the number comes from a `Uint32Array` or anywhere else still stands. The array type only specifies how the values are **stored**. When you take a value out e.g. by indexing `arr[0]`, it is just a number again. You can check that `typeof arr[0] == "number"`. And in JS, numbers are always doubles, but you do get [an effective range of 2^53](https://stackoverflow.com/q/307179/). The bitwise operators internally turn the number into a 32-bit integer first. – Aurel Bílý Feb 19 '20 at 18:25
  • That is pretty complex. Everything in JavaScript is a double but with bitwise operations it gets converted to a 32 bit integer - signed or unsigned? I'm going to run. a quick test to see. Will post the snippet. – jennifer Feb 20 '20 at 16:10
  • @j.a. [MDN says](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators) all bitwise operators treat the operands as signed integers, except for `>>>`. – Aurel Bílý Feb 20 '20 at 16:15
  • I just read that, it seems that >> preserves the sign bit while >>> shifts in 0s. – jennifer Feb 20 '20 at 16:18