• (nodebb)

    0.0 - x, where x < 0 would be the same as x * -1.

    Two points:

    1. Why do you think it makes a difference whether x is positive, negative, or even zero?

    2. Why do people feel compelled to write x * -1 as a way to negate x, instead of -x?

  • Michael R (unregistered) in reply to Steve_The_Cynic

    re #2: I have seen this so many times before too and came to the conclusion: people don't know any better. It's sad.

  • Anon (unregistered) in reply to Steve_The_Cynic

    #1) it is said in the context of explaining how this construct would work to produce an absolute value.

    #2) they both compile to a single NEG opcode so it doesn’t matter.

  • (nodebb)

    This fundamental misunderstanding of the simplest, most basic math is the real WTF. Sorry Kendall, please find another career. There is no excuse for this code. The "typo" I can understand. All the rest of it...

    If people think I'm too harsh: My predecessor had about the same level of math stills. Didn't even understand negative values, yet still wrote control loops for the temperature of overheated steam. It's plain scary.

    Addendum 2024-08-21 08:25: overheated = superheated

  • Vera (unregistered)

    The line between underthinking and overthinking is thin, and some people are playing hopscotch with it without even knowing it.

  • Sauron (unregistered)

    That code was not written by Kendall.

    It was written by 0.0 - Kendall

  • (nodebb)

    short abs(short x) { short mask = x >> (sizeof(short) * 8 - 1); return (x + mask) ^ mask; }

  • (nodebb)

    Are there really still languages out there where you need to reinvent abs()? If that's indeed what's attempted here...

  • Pabz (unregistered) in reply to Domin Abbus

    You could be right - maybe Kendall doesn't understand math and needs to find another career. At the same time this code could have been written at 3am after working all day because the boss had made a promise to a customer!

  • (nodebb) in reply to Anon

    they both compile to a single NEG opcode so it doesn’t matter

    If the compiler is intelligent enough to do that optimisation

    If the architecture has a NEG opcode.

  • (nodebb) in reply to Domin Abbus

    Because, of course, you've never written code that stupid in your career, not even when you were really tired or under great pressure.

  • Brian (unregistered) in reply to Erik

    If people only did the things they need to, this site would be pretty boring. Much more interesting when you don't need to do something, but you come up with a "creative" way of doing it anyway.

    But in this case, it's not just about the abs, as evidenced by the other line there. I've seen code like this before, looks like resizing a box in a UI: left side is out of bounds, so move it in bounds and decrease the width to keep the right side in the same place.

  • (nodebb) in reply to jeremypnet

    No. Not to that extent. Yes, I've done some stupid stuff, howlers even, and costly ones at that. But I have never, ever substracted a value from zero, just to simulate a negation. If you're that clueless of the mathematical tools at your disposal, then get the out of the kitchen before someone gets burned. This is not a sleep-deprived brain-fart, it is far worse and deeply unsettling.

    To me, that's on the level of an obstacle runner not knowing how to properly ties the shoelaces.

  • Jens (unregistered)

    The fact that width is also adjusted leaves me with a little bit of doubt that the purpose was to make x a positive number. If x is a coordinate and width is... width, this code will move whatever is placed outside the normal bounds of a window to inside the window, and reduce the width so the right edge is in the same spot. Of course, that could have been achieved with simply x = 0 and the same width adjustment, so there's that, but x = 0 wouldn't be very symmetrical with the change to width, so my best guess would be that the calculation 0.0 - x came first, and the x += and width -= came after.

  • (nodebb)

    Are we really going to ignore the width variable when assuming this was intended to do just an abs?

    The operation we are seeing here is

    if(x < 0) {
        x = 0
        width += x
    }
    

    Equivalent to

    x = (x>0) * x
    // width unchanged
    

    if the language allows it.

    We can't even for sure say what the bug was, considering the presence of "width" inside the conditional block.

  • (nodebb) in reply to Anon

    they both compile to a single NEG opcode so it doesn’t matter

    In addition to what @jeremypnet said, it does matter, for a reason that falls into the "90%" side of the 90%/10% split of a programmer's job.

    The 10% side is all that programming junk, designing stuff, writing code and all that. The 90% side is "communicating with other humans", and if you write code in a slightly weird way, you're communicating "my code does this in a weird way for some weird reason", and you're not communicating the reason. (Audience of this communication: your fellow programmers, including yourself in six months or a dozen years) -x is the "non-weird" way to write negation, so nobody much will look twice other than to verify that negation is really needed. 0 - x and x * -1 (and even -1 * x) are weird ways to write it, and I'm likely to spend time wondering what's so special about it that it can't be just written as -x, going even so far as to see if there are weird things like inconsistencies between your overloaded operator -(const MyThing&), operator -(double, const MyThing&) and MyThing::operator *(double).

    That's why it matters.

  • (nodebb) in reply to Steve_The_Cynic

    Why do people feel compelled to write x * -1 as a way to negate x, instead of -x?

    I suspect they conceptualize - as a negative sign on number literals, not as a unary operator. So you can write -3, but not -x. Even if they know this intellectually, it's not intuitive to them, so they find x * -1 a better way to express their intent.

    Any compiler that doesn't produce the same code for both (assuming no operator overloading that actually makes them different, which would be a WTF itself) is not worth considering.

  • (nodebb)

    There is an issue with this code nobody here seem to have spotted. If this is C/C++ or C#, heck even JavaScript, x is literally cast to float by 0.0 - x. Now for C variants this is really bad, because double operations are better performing, in fact C# only does double operations, the float will be converted back to a double before the subtraction. Granted, Roslyn now does this literal conversion in most cases automatically, but boy, this is a bigger code smell than anything else in this snippet IMO.

    BTW the correct way to 2s-complement a number in C syntax languages is x = -x; for those interested 1s-complement is x = ~x. x *= -1 would be equally a bad style because now you are at the mercy of the compiler to optimize that to a 2s-complement operation.

  • Anon (unregistered) in reply to jeremypnet

    NEG predates IMUL immediate on x86 architectures, and far from it requiring a compiler “intelligent” enough to optimise, I suspect there has never been a compiler that would select the longer (in both space and time dimensions) IMUL immediate over NEG unless explicitly forced to.

  • Anon (unregistered) in reply to Steve_The_Cynic

    x * -1 (and even -1 * x) are weird ways to write it, and I'm likely to spend time wondering what's so special about it that it can't be just written as -x

    If you’re this shook by the concept of multiplying a number by negative one that your productivity would immediately grind to a halt, then I think you might be in the wrong career?

  • Anonymous Coward (unregistered)

    I have to say, kudos to Kendall for publishing their own WTF. That shows courage, an honest unflinching self-awareness, and a strong desire to improve.

  • Tinkle (unregistered) in reply to Rick

    Hello Rick.

    Sorry to say this but that is a bigger WTF than the original code. It is obscure, buggy and adds nothing except fixed execution time.

    A better abs would be: short abs(short x) { return (x<0) ? -x : x; } or even make it a macro so it would work inline and with any type.

    It could be changed to:

    short abs(short x) { short mask = x >> (sizeof(short) * 8 - 1); return (x ^ -mask) + mask; } // If the high bit is set exor by -1 and add 1, otherwise do nothing.

    Although I would still say that was a WTF. The only time I know that fixed execution time is required is in a security system and none (as far as I know) require abs.

    Sorry to be so pedantic.

  • BZ (unregistered)

    For some reason I'm never sure whether -x will work, especially if x is already negative, even though I'm pretty sure it will work in most languages.

  • Foo AKA Fooo (unregistered) in reply to MaxiTB

    Nope. 0.0 is double in C and C++. 0.0f would be float. https://en.cppreference.com/w/cpp/language/floating_literal

  • Foo AKA Fooo (unregistered) in reply to Foo AKA Fooo

    And even if 0.0 was a float literal, an operation between float and double (assuming x is double) would cast both arguments to double. In no case would x be cast to float for the subtraction.

  • (nodebb) in reply to Barry Margolin

    So you can write -3, but not -x.

    Yeah, that's a good point, because they totally never saw -x in any mathematics lesson. Never, not once.

    Here endeth (for the moment) the sarcasm.

  • ismo (unregistered) in reply to Anon

    Sometimes microsecond is eternity. Usually not. So everything depends on the context where the code is run. Old timers tend to think about these things even tough it is no more necessary.

  • LZ79LRU (unregistered) in reply to Steve_The_Cynic

    Because the intention of the code is much easier to spot while casually scrolling through. It's the same as writing if (x == true) vs if(x) or adding explicit braces and spacing even for a single clause if.

  • Mad Rabiit (unregistered) in reply to LZ79LRU

    Hi LZ79LRU:

    Don't do comparasions on booleans. if(x) and if(x==true) are not the same thing. if(x) evaluates as true if x is non zero if(x==true) only evaluates as true if x is 1 (for most languages, but not all.)

    Ugly as it is, there are reasons why people do things like if(!!x==!!y), becauses it forces the evaluation of each boolean variable, rather than doing a comparasion.

  • (nodebb) in reply to jeremypnet

    If the architecture has a NEG opcode.

    Most practical architectures do; it's really easy to implement in the ALU if you already have a SUB opcode.

Leave a comment on “Do a Flip”

Log In or post as a guest

Replying to comment #:

« Return to Article