• Industrial Automation Engineer (unregistered)

    bitTest (frist, 0)

  • (nodebb)

    (gotta think about endianness!),

    Sort of. It's more about making the bits in the resulting string be numbered in the modern conventional order (0 => LSbit, 1 => LS+1bit, etc.)(1).

    (1) Three other numbering patterns have been used in the past: LSBit = 1, MSBit=0, MSBit=1, but LSBit=0 has the advantage that it corresponds 1:1 with the values of (1 << bitnum) which none of the others do.

    I expect this code to be uploaded to NPM and turned into a microframework that ends up powering 75% of web applications by the end of the week, as a dependency-of-a-dependency-of-a-dependency.

    And six months after that, the original uploader will delete it from NPM in a fit of pique. See e.g. left-pad.

  • my name (unregistered) in reply to Steve_The_Cynic

    you obviously didn't read the ERV

  • WTFGuy (unregistered)

    As the historians almost say:

    Those who don't know their programming language are doomed to reimplement it.

  • Brian (unregistered)
    I expect this code to be uploaded to NPM and turned into a microframework that ends up powering 75% of web applications by the end of the week, as a dependency-of-a-dependency-of-a-dependency.

    And that is why NodeJS is TRWTF

  • (nodebb)

    I expect this code to be uploaded to NPM and turned into a microframework that ends up powering 75% of web applications by the end of the week, as a dependency-of-a-dependency-of-a-dependency.

    I'm on it!

  • (nodebb)
    But think about the readability benefits! Instead of writing the cryptic if (variable & (1 << bit)), which is nigh unreadable, you can now say if (bitTest(variable, bit))

    I think bitTest... is more immediately readable, so I would be fine with someone writing that function. This implementation, though, not so much.

  • (nodebb)

    Don't forget - it will be published with a subtle off-by-2 bug (hey, their off-by-1 bug was off) that tests the wrong bit. And everyone will depend on that behavior so it can't be fixed.

  • Argle (unregistered) in reply to Dragnslcr

    I'm with you there. Broadly speaking, I was OK with the function concepts. After all, it's not such a bad thing to write in C/C++'s preprocessor. But I taught programming for enough years to recognize the work of someone who didn't really know what he/she was doing. I once had a student create a giant switch statement to uppercase a string. And I knew he sat through my lecture that include strupr().

  • xtal256 (unregistered)
    Comment held for moderation.
  • lyricslogy (unregistered)
    Comment held for moderation.
  • (nodebb)

    In our software, we have a global array called "Bits" such that Bits[3] = 1 << 3. I guess we figured it was more readable / easier to write? Not sure if the performance takes a hit because of it. I would assume that a left shift is much quicker than reading into an array held in memory.

    If I could, I would try replacing it with a macro. But as far as I'm aware, you can't have a macro e.g. #define Bits[x] (1ull << x). Might have to consider a replace-all with a regex, being careful since the index might not be an integer. Might be asking for more pain than it's worth if I try.

  • Duke of New York (unregistered)

    Yeah let's skip ahead to the part where the maintainer deletes the package from NPM to strike a blow against corporate tyranny.

  • Sole Purpose Of Visit (unregistered) in reply to prueg

    If it's a const static array, I would assume that a decent compiler would optimise that substitution out; so, not a bad idea at all. At the very worst, I'd expect the cost to be nothing more than an ADD base, offset ... which is hardly a performance killer in most instances.

  • /df (unregistered)
    Comment held for moderation.
  • Duke of New York (unregistered) in reply to Argle

    The programmer knew exactly what they were doing. Every method is used as documented, boundary conditions are checked, and the function does what it's supposed to. This is more a problem of choosing the worst possible thing to do.

  • (nodebb) in reply to Duke of New York

    Which boundary checks? There are none, yet Javascript supports up to 52 bits integers whereas the loop hopefully assumes 32 to be the limit of its input.

    Never mind that (I agree with the rest). What was the programmer thinking? Perhaps that it's easy to adapt testBit whenever ternary bits become the norm? Occam's razor suggests a more plausible explanation, i.e. that no measurable thoughts were involved at all.

  • Duke of New York (unregistered)
    Comment held for moderation.
  • NoLand (unregistered)

    Late to the show, but here are some observation

    • bit-wise operations in JS imply a fix-point conversion to 32-bit integers, while Number.toString(2) does not. Meaning, this will give you an up to 53 character string and a bit store of 53 bits for 0 … Number.MAX_SAFE_INTEGER.

    • however, the code handles only 32 bits explicitly. (It will still work with a bit indiex higher than that, but it's a strong indication for the the code not exploiting the entire range provided by Number.toString(2))

    • the byte order in the check is still in LSB-order: (4).toString(2) returns "100" and the reverse order string is "001" with bit = 2 still checking the hi-bit in 4

    • as usual, there is a lot of code that has no effect. Just like with sparse arrays an out-of-bounds string index returns undefined, which always yields false in a comparison with any defined value. So the loop filling the array to 32 elements does nothing, but wasting heap and runtime.

    • the if-else on a boolean return value is superfluous,return temp[bit] == '1' does the same.

  • TGJ Gilmore (unregistered)

    I really like this post and realise the code example is for teaching purposes. However, I would like to offer the reader some 'refinements'.

    1. The for loop can be placed by using a padEnd to fill out the string to represent 32bits. Alternatively, thepadStart` could be used and the order of the bits kept in a more conventional order.
    2. There is no need to reverse the bit order if the at method is used with a negative offset.
    3. The evaluation to Boolean can also be simplified, removing the need for the if statement, by prefixing the selected character with + to make it a number than casing it to Boolean using !!. Here is the finished function:
    function myBitTest( value, bit ) {
      let bitMask = value.toString(2).padStart('0', 32);
      return !!+bitMask.at(1 - bit);
    }
    

Leave a comment on “A Bit of Javascript”

Log In or post as a guest

Replying to comment #:

« Return to Article