• LCrawford (unregistered)

    I'll admit, my first reaction was surprise that Rust allows the >> operator as right shift and thus doesn't require the binary manipulation word salad of the example.

  • pgrobban (unregistered)

    What is a use case for getting the first 42 bits of a number?

  • A. (unregistered) in reply to pgrobban

    When using some low-level protocols, you sometime have to deal with case like that :

    • First 42 bits are the value of whatever
    • Next 5 bits are something else
    • etc.
  • (nodebb)

    To use the bit shift operator one has to know that it exists, which means they have to know what bits are.

  • 516052 (unregistered)

    Everyone knows what bits are. It's those things that are like pieces but smaller and can't be put back together.

  • witchdoctor (unregistered)

    Depending on how many fields I'm parsing I'd be tempted to look up how to do bitfields in Rust instead of using shifts. I kind of doubt that they work like this though.

  • Shirkasso (unregistered) in reply to pgrobban

    Why would you want to water your garden using a hose? Use a bucket. Buckets are proofen tech when it comes to avoiding the question and not contributing to the discussion.

  • Shiwa (unregistered)

    Going the built-in route, it can obviously be simpler. Going the integer arithmetic route, it also can be simpler : divide by power of 2, rounded down. Going the string route, it still can be simpler : convert to string, slice, pad, convert back.

    In fact, you probably could have a simpler implementation by calling an online convertor…

  • (nodebb)

    It's not really overcomplicated if you don't use reduce.

  • 516052 (unregistered)

    To be honest I am not a fan of bit shifting. Sure, it's efficient but its also inconvenient to debug and analize in any way, shape or form. And you know that sooner rather than later you are going to have to debug that bloody thing to see what flag is set on a bit half way down the line. And not everyone has so many years of experiance that they can just convert decimal numbers to binary in the head like I do.

    So honestly I see nothing bad with converting it to a binary string (most languages these days can do so nativelly with built in functions) and itterate through it with a for loop. Less efficient but much more transparent. But like, do it right and not what ever the hell that guy did.

  • Zygo (unregistered)

    I would say it's like reading Perl code, with the funky syntax and map operators and binary unpack and whatnot, but in Perl we'd just write "$snowflake >> 22".

  • IPGuru (unregistered)

    Shurely this refers to the LAST 42 bits The 1st bit is bit 0 shifting righ wold move the high bits down sremoving the first 22 bits

  • Bart (unregistered)

    If your language can convert from number to a binary representation in a string, then certainly it can do the reverse as well. At least you won't have to iterate the sring and do 22 iterations of pow() yourself.

  • Joining the Party (unregistered) in reply to witchdoctor

    Great to see Rust joining the party for WTF's! The author of this code must not like intro chapters...

    As for bit-fields in rust, here's a nice article: https://immunant.com/blog/2020/01/bitfields/

    They look a lot like C-style, but you can choose between a macro that looks like a struct and an actual struct.

  • Al Pine (unregistered)

    I don’t know Rust so I’m l left to wonder: does this code deal correctly with leading zeros?

  • Sole Purpose Of Visit (unregistered)

    Quick nit-pick: you'd want an unsigned int here, in any language. Not that it's relevant.

    I'm actually not a fan of bit-shift operators, because they are less intuitive than you'd think. But in this case (Rust) we actually have a sensible type to use, ie a BitArray. You set up a BItArray by telling it the MSB and the size (I believe this has to be a native type, so u64 in this case). You use it either by taking a bit slice, (you can even invert the endian-ness!) or by defining the start and end bits (open on the start, closed on the end).

    You can therefore program Rustically (in deference to Pythonically). Or, obviously, in this case, you can program Idiotically.

  • Carl Witthoft (google) in reply to pgrobban
    What is a use case for getting the first 42 bits of a number?
    Well duh, that part of the number is the answer to The Question.
  • Barf4Eva (unregistered)

    holy fuckballs

  • Brian Boorman (unregistered)

    If I wanted the first 42 bits, I'd do:

    snowflake &=0x3FFFFFFFFFF;

    because you know, bits are numbered with 0 on the right.

  • Sole Purpose Of Visit (unregistered) in reply to Brian Boorman

    Except when they're not.

  • (nodebb)

    I would say that for the typical binary protocol situation where bit operations are needed, there has to be a stream wrapper of some sort which handles these things opaquely. Basically, if you need to send a number that requires 42 bits, there should be a method like "void WriteAsBits(long value, int numberOfBits)" and corresponding read method. Assuming this is for sending a packet or a message of some sort, there should be a class for this message type, and it should have "void SerializeTo(Stream stream)" which has the necessary calls to WriteAsBits, and the corresponding DeserializeFrom.

    Addendum 2021-08-05 13:08: Yes yes there is a temptation to create a format specifier system and an engine to process the format, like "props.Add(x=>x.LongProp, 42);" then both serialization and deserialization can be handled by the same logic, reducing the chance of making mistakes, such as mismatched protocols. But keep in mind the inner platform anti pattern. This will work for simple properties, but once you go to complex types, it can spiral out of control.

  • Captain Obvious (unregistered)

    Another solution in search of a problem, once again brought to you by Rust.

  • Loren Pechtel (unregistered)

    Whoever wrote this probably only knows bits in the context of naughty bits, and those aren't supposed to be used in public. Hence this workaround.

  • Worf (unregistered)

    Bitfields are non-portable in C. I know, I've had to port code using bitfields to work on opposite endianess. That is, I was building on a little endian machine (your bog standard x86 PC) building a flash image for a big-endian machine running Linux.

    And the code uses bit fields. to represent metadata, so I had to write a lot of code to convert the structure as it was held on my PC into something that would work once flashed onto the destination hardware.

    Bit fields suck, in other words. You're better off using standard bit operators and bit shifts.

  • Argle (unregistered)

    Ah, this year's first entry in the Obfuscated Rust competition.

  • James (unregistered) in reply to Bart

    When you realize that a bitstring is just a summation of 0s and 1s raised to powers of 2, but fail to realize that you can use Horner's rule.

  • Chris (unregistered)

    Oh wow. This triggers me on so many levels.

    You have a number. You want a different number, based on some function of that number. Strings don't need to come into it! Why do so many people have to deal with numbers as strings?!?! The only time to consider numbers as strings is for display!!!

    But seriously, even after converting to a bit string, they couldn't just take a substring and convert that back directly?

    +1 for being careful on right-shifts, if the integer is signed. Stupid Java and their "no-one needs unsigned ints" and "oh, you want unsigned ints, well, I suppose you can use boxing classes to do that, you weirdo" and needing to know the difference between an arithmetic bitshift and a logical bitshift.

  • Wizofaus (unregistered) in reply to Brian Boorman

    Glad I wasn't the only one thinking that! Though I'm not sure why I'd generally assume the first bit of a number is the rightmost the first decimal digit is the leftmost. If it said the leftmost 42 bits all would have been clear.

  • 516052 (unregistered) in reply to Chris

    Because some times a number is not actually a number but is in fact logically a string or array of booleans or some such. And yet you get it as a number for various reasons including but not limited to lazy programmers, clever programmers, hardware or software limitations and malice.

    In those cases casting it to what ever it logically is and than working with that as opposed to being clever and writing code that mangles a decimal integer produces code that is easier to write, understand and debug.

  • BB (unregistered) in reply to 516052

    .. yes, sooner or later everything will have to be debugged. Even in Rust. Lack of understanding of bits and bytes is NOT going to help.

  • (nodebb)

    for.me().the().honkin().big().wtf().isnt().the().code().but().the().fact().that().some().genius().decided().this().cobol_envy().gibberish().is().more().meaningful().than().writing("c = a + ( b * d )");

  • (nodebb) in reply to Wizofaus

    If it said the leftmost 42 bits all would have been clear.

    Possibly, but we have specific terminology for exactly this situation. We say "the 42 most significant bits".

  • (nodebb) in reply to 516052

    We are not told what the most significant 42 bits of this number represent. It could be a collection of flags in which case, the logical representation is an array of booleans. Or it could be a number, as many bit fields in network packets are. In this case, the logical representation would be an integer value. What it almost certainly is not is a highly compressed version of a string containing only ASCII characters 0x30 and 0x31.

    Honestly, if you can't cope with bit shifting operations, you probably have no business in programming. If you can't convert a 64 bit number from decimal into binary in your head like I can't (and probably like you can't in spite of your claim), well your debugger certainly can, or you need to get a better debugger.

Leave a comment on “A Bit Overcomplicated”

Log In or post as a guest

Replying to comment #:

« Return to Article