• (cs) in reply to Lord of All!

    Any consultant getting more than about $20 for this code would count as highly paid.

  • Evan (unregistered) in reply to chubertdev
    chubertdev:
    Evan:
    Working the units in doesn't do anything to help solve the problem, which is you (or at least I) can't look at 1000000000 and tell immediately what it is. 1 billion? 100 million? 10 billion? You have to count zeroes. Come back to that code a couple weeks later? Count them again.

    If you say "MAX_AIRSPEED_BLAH_BLAH_BLAH = 1*BILLION" there is no question.

    I personally do this long before that... starting in the 10 or 100 thousands if it's an even multiple of 1000.

    Counting zeroes is so tough!

    Nothing at that level is very tough. Is it really hard to find out that FooBar is a class in one place but a variable in another place? Or the structure of the following code:

    if (x) {
      int z = f(x);
      if (z)
               z++;
        else {
           z--;
           y--;
        }
      y += z;
    }
    And yet you'd probably be fairly hard-pressed to find someone who thinks that inconsistent naming schemes and random indentation (so long as a block is indented to a consistent level beyond the previous block, as is the case for my example) isn't a bad thing.

    The point of coding standards and things like that is to reduce the little things you have to think about to leave more brain power for the parts that are actually hard.

  • maurizio (unregistered) in reply to faoileag

    So, magic number to avoid typing errors ? Well, add a CRC on a comment, at the end of line. This works also for other kind of constants, like strings, and even for variable names.

    Maurizio

  • gallier2 (unregistered) in reply to gnasher729

    You can also use exponential format, at least in C it works without hassle.

    1 billion 1e9 1 million 1e6 1 hundred thousand 1e5

  • Evan (unregistered) in reply to gallier2
    gallier2:
    You can also use exponential format, at least in C it works without hassle.

    1 billion 1e9 1 million 1e6 1 hundred thousand 1e5

    The type of 1e9 is double. The type of 1000000000 is int. You probably want a cast in there too. Though that's actually a pretty reasonable suggestion.

  • (cs) in reply to My C is better than that
    My C is better than that:
    Ah, you want FORTRAN, then.

    The peculiarities of FORTRAN parsing mean that

          I=1000000000

    and

          I = 1 000 000 000

    are the same thing...

    And in C you can write

        I = 1, 000, 000, 000; 

    So much more obvious than the fortran. It'll compile just fine too.

    You're kidding, right? In C, you can write

        I = 1, 000, 000, 000; 

    but it doesn't mean what you think. I gets assigned the value 1 and the comma operators effectively cause the 0's to be ignored.

    I do believe I will be 0, not 1. It discards all but the last expression.

  • Chelloveck (unregistered)

    I regularly define constants for common numbers, even for things like 1000.

    K = 1000 M = 1000K G = 1000M T = 1000*G

    SECOND = 1 MINUTE = 60SECOND HOUR = 60MINUTE DAY = 24*HOUR

    delta = this_date - last_date if delta > 4HOUR and file.st_size < 2M {...}

    Beats the heck out of mentally dividing by 60, 3600, or 86400; or counting up the zeros. (Yes, I also define things like "FILE_MAX_AGE = 4*HOUR", then use "if delta > FILE_MAX_AGE". It's a simplified example. Don't hassle me about best practices.)

  • My C is better than that (unregistered) in reply to redtetrahedron
    redtetrahedron:
    My C is better than that:
    Ah, you want FORTRAN, then.

    The peculiarities of FORTRAN parsing mean that

          I=1000000000

    and

          I = 1 000 000 000

    are the same thing...

    And in C you can write

        I = 1, 000, 000, 000; 

    So much more obvious than the fortran. It'll compile just fine too.

    You're kidding, right? In C, you can write

        I = 1, 000, 000, 000; 

    but it doesn't mean what you think. I gets assigned the value 1 and the comma operators effectively cause the 0's to be ignored.

    I do believe I will be 0, not 1. It discards all but the last expression.

        I = 1, 000, 000, 000; 

    makes I 1.

        J = ( 1, 000, 000, 000 ); 

    makes J 0.

  • (cs) in reply to Shill
    Shill:
    While I understand where you are coming from, the OP is justified in his calling the constants ONE and ZERO. It is standard in mathematics to refer to the multiplicative identity and additive identities in a ring as 1 and 0 respectively, even if the ring doesn't contain numbers. In some cases the ring might even contain the traditional 1 and 0 and these will NOT correspond to the ring's 1 and 0.
    well then ...
    private final static Foo ZERO_OF_THE_RING = ...
    private final static Foo ONE_OF_THE_RING = ...
    private final static Foo LORD_OF_THE_RING = ...
    
  • (cs) in reply to Julian
    Julian:
    Would be nice if underscore characters were allowed in numbers;
    The Ada programming language allowed that.
    http://docs.oracle.com/javase/7/docs/technotes/guides/language/underscores-literals.html Can't believe noone brought this up yet!
  • (cs) in reply to Evan
    Evan:
    chubertdev:
    Evan:
    Working the units in doesn't do anything to help solve the problem, which is you (or at least I) can't look at 1000000000 and tell immediately what it is. 1 billion? 100 million? 10 billion? You have to count zeroes. Come back to that code a couple weeks later? Count them again.

    If you say "MAX_AIRSPEED_BLAH_BLAH_BLAH = 1*BILLION" there is no question.

    I personally do this long before that... starting in the 10 or 100 thousands if it's an even multiple of 1000.

    Counting zeroes is so tough!

    Nothing at that level is very tough. Is it really hard to find out that FooBar is a class in one place but a variable in another place? Or the structure of the following code:

    if (x) {
      int z = f(x);
      if (z)
               z++;
        else {
           z--;
           y--;
        }
      y += z;
    }
    And yet you'd probably be fairly hard-pressed to find someone who thinks that inconsistent naming schemes and random indentation (so long as a block is indented to a consistent level beyond the previous block, as is the case for my example) isn't a bad thing.

    The point of coding standards and things like that is to reduce the little things you have to think about to leave more brain power for the parts that are actually hard.

    If you think that having difficulty counting zeroes and inconsistent naming schemes are on par with each other, for the love of all things holy, please find another industry.

  • Lord Javac (unregistered)

    I don't write Java, but doing a quick search shows that the substring method on String takes two indices, not a start and length. So, someString.substring(0,29) returns the first 30 characters of said string (since we start counting at 0). So while their code was obfuscated and redundant, I believe it was correct.

    http://docs.oracle.com/javase/7/docs/api/java/lang/String.html

  • gallier2 (unregistered) in reply to Evan
    Evan:
    gallier2:
    You can also use exponential format, at least in C it works without hassle.

    1 billion 1e9 1 million 1e6 1 hundred thousand 1e5

    The type of 1e9 is double. The type of 1000000000 is int. You probably want a cast in there too. Though that's actually a pretty reasonable suggestion.

    Works without cast in most cases thanks to int promotion rules (at least in C, C++ I don't give a s...). 1e9 is converted to long. Of course depends a bit on the context.

  • Evan (unregistered) in reply to gallier2
    gallier2:
    Works without cast in most cases thanks to int promotion rules (at least in C, C++ I don't give a s...). 1e9 is converted to long. Of course depends a bit on the context.
    Some compilers will warn about the double->int conversion. (Spuriously, but that doesn't mean it can't be a problem if you have good warning practices.) In C++ (/Java/etc.), you could have a situation where the wrong overload is chosen, or the wrong template parameter is inferred.
    chubertdev:
    If you think that having difficulty counting zeroes and inconsistent naming schemes are on par with each other, for the love of all things holy, please find another industry.
    I'd say that the only reason they aren't is because of how frequently they arise. If typical code had lots of 100000 10000000 1000000s every couple lines, I think that it really would be as important.

    But the fact that it's infrequent that this situation arises doesn't mean that when it does you shouldn't take steps to try to improve things. If it was hard to do or something like that that'd be one thing, but even if you defined a special "BILLION" then used that you're talking one extra line of code. The improved-readability to effort-expended ratio is what matters, and in this case I think is very favorable.

  • (cs) in reply to My C is better than that
    My C is better than that:
    redtetrahedron:
    My C is better than that:
    Ah, you want FORTRAN, then.

    The peculiarities of FORTRAN parsing mean that

          I=1000000000

    and

          I = 1 000 000 000

    are the same thing...

    And in C you can write

        I = 1, 000, 000, 000; 

    So much more obvious than the fortran. It'll compile just fine too.

    You're kidding, right? In C, you can write

        I = 1, 000, 000, 000; 

    but it doesn't mean what you think. I gets assigned the value 1 and the comma operators effectively cause the 0's to be ignored.

    I do believe I will be 0, not 1. It discards all but the last expression.

        I = 1, 000, 000, 000; 

    makes I 1.

        J = ( 1, 000, 000, 000 ); 

    makes J 0.

    Oh, so the assignment has a higher precedence than the comma. Did not know that.

  • (cs) in reply to Lord Javac
    Lord Javac:
    I don't write Java, but doing a quick search shows that the substring method on String takes two indices, not a start and length. So, someString.substring(0,29) returns the first 30 characters of said string (since we start counting at 0). So while their code was obfuscated and redundant, I believe it was correct.

    http://docs.oracle.com/javase/7/docs/api/java/lang/String.html

    Are you just trolling or to stupid to read the very JavaDoc you cite?

    http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#substring(int, int)

    Lord JavaDoc:
    Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.
  • (cs) in reply to Evan
    Evan:
    I'd say that the only reason they aren't is because of how frequently they arise. If typical code had lots of 100000 10000000 1000000s every couple lines, I think that it really would be as important.

    But the fact that it's infrequent that this situation arises doesn't mean that when it does you shouldn't take steps to try to improve things. If it was hard to do or something like that that'd be one thing, but even if you defined a special "BILLION" then used that you're talking one extra line of code. The improved-readability to effort-expended ratio is what matters, and in this case I think is very favorable.

    I think we'll just have to agree to disagree. I don't see why anything more than a comment is necessary.

    100000 //one hundred thousand
    10000000 //ten million
    1000000 //one million
    
  • Norman Diamond (unregistered) in reply to Evan
    Evan:
    chubertdev:
    If you think that having difficulty counting zeroes and inconsistent naming schemes are on par with each other, for the love of all things holy, please find another industry.
    I'd say that the only reason they aren't is because of how frequently they arise. If typical code had lots of 100000 10000000 1000000s every couple lines, I think that it really would be as important.
    Long long ago in a galaxy far far away, a company abbreviated RCA tried to compete with another company abbreviated IBM. RCA's computer division was losing money.

    RCA closed down their computer division. But RCA didn't close down their computer division because it was losing money. They knew they were losing money trying to compete with IBM, and they decided they would try anyway. Losing money wasn't the reason they gave up.

    RCA closed down their computer division because they miscalculated the AMOUNT of money they were losing. When they looked at the amount of money they thought they were losing, they decided they couldn't afford to compete any more. They didn't know that they were actually losing an affordable amount.

    RCA's computations had made an off-by-zero error.

  • Norman Diamond (unregistered) in reply to chubertdev
    chubertdev:
    Evan:
    I'd say that the only reason they aren't is because of how frequently they arise. If typical code had lots of 100000 10000000 1000000s every couple lines, I think that it really would be as important.

    But the fact that it's infrequent that this situation arises doesn't mean that when it does you shouldn't take steps to try to improve things. If it was hard to do or something like that that'd be one thing, but even if you defined a special "BILLION" then used that you're talking one extra line of code. The improved-readability to effort-expended ratio is what matters, and in this case I think is very favorable.

    I think we'll just have to agree to disagree. I don't see why anything more than a comment is necessary.
    100000 //one hundred thousand
    10000000 //ten million
    1000000 //one million

    You KNOW what's going to happen if you depend on comments.
    100000 //one hundred thousand
    

    100000000 //ten million 1000000 //one million

  • (cs) in reply to Jay

    Actually that's incorrect plus it's worse than that. Literal expressions have the possiblity to be evaluated at compile time. A gcc snippet best shows the overhead for a simple "printf("%d\n",1+3)" expression..

        movl    $3, %esi
        movl    $.LC0, %edi  //"%d\n"
        movl    $0, %eax
        call    printf
    

    ..whereas if you declare a couple on integers ONE,TWO "printf("%d\n",ONE+TWO)" now becomes..

        movl    $1, -8(%rbp)  //ONE=1
        movl    $2, -4(%rbp)  //TWO=2
        movl    -4(%rbp), %eax //TWO
        movl    -8(%rbp), %esi //ONE
        addl    %eax, %esi
        movl    $.LC0, %edi //"%d\n"
        movl    $0, %eax
        call    printf
    
  • (cs) in reply to Norman Diamond
    Norman Diamond:
    chubertdev:
    Evan:
    I'd say that the only reason they aren't is because of how frequently they arise. If typical code had lots of 100000 10000000 1000000s every couple lines, I think that it really would be as important.

    But the fact that it's infrequent that this situation arises doesn't mean that when it does you shouldn't take steps to try to improve things. If it was hard to do or something like that that'd be one thing, but even if you defined a special "BILLION" then used that you're talking one extra line of code. The improved-readability to effort-expended ratio is what matters, and in this case I think is very favorable.

    I think we'll just have to agree to disagree. I don't see why anything more than a comment is necessary.
    100000 //one hundred thousand
    10000000 //ten million
    1000000 //one million

    You KNOW what's going to happen if you depend on comments.
    100000 //one hundred thousand
    

    100000000 //ten million 1000000 //one million

    And then I get to use the blame feature. :D

  • Evan (unregistered) in reply to SD123
    SD123:
    Actually that's incorrect plus it's worse than that. Literal expressions have the possiblity to be evaluated at compile time. A gcc snippet best shows the overhead for a simple "printf("%d\n",1+3)" expression..
        movl    $3, %esi
        movl    $.LC0, %edi  //"%d\n"
        movl    $0, %eax
        call    printf
    

    ..whereas if you declare a couple on integers ONE,TWO "printf("%d\n",ONE+TWO)" now becomes..

        movl    $1, -8(%rbp)  //ONE=1
        movl    $2, -4(%rbp)  //TWO=2
        movl    -4(%rbp), %eax //TWO
        movl    -8(%rbp), %esi //ONE
        addl    %eax, %esi
        movl    $.LC0, %edi //"%d\n"
        movl    $0, %eax
        call    printf
    
    GCC constant folds ONE + TWO if you turn on optimization (even -O1 is sufficient). If you compile as C++ code and mark the ints as const (which they better be regardless of C/C++ unless you require supporting crap compilers that don't support it), GCC will fold ONE+TWO even without optimization. Clang and Intel's compiler both behave the same way (except that with no optimization flags, ICC does some optimizations that folds a non-const ONE+TWO by default).
  • Evan (unregistered) in reply to Evan
    Evan:
    Clang and Intel's compiler both behave the same way (except that with no optimization flags, ICC does some optimizations that folds a non-const ONE+TWO by default).
    To correct myself: Clang and Intel both do better than GCC with -O0: under those compilers, the folding occurs (with a const int) under C as well as C++.
  • v (unregistered)

    The real WTF is how the article tried to explain the WTF.

  • (cs) in reply to Norman Diamond
    Norman Diamond:
    chubertdev:
    Evan:
    I'd say that the only reason they aren't is because of how frequently they arise. If typical code had lots of 100000 10000000 1000000s every couple lines, I think that it really would be as important.

    But the fact that it's infrequent that this situation arises doesn't mean that when it does you shouldn't take steps to try to improve things. If it was hard to do or something like that that'd be one thing, but even if you defined a special "BILLION" then used that you're talking one extra line of code. The improved-readability to effort-expended ratio is what matters, and in this case I think is very favorable.

    I think we'll just have to agree to disagree. I don't see why anything more than a comment is necessary.
    100000 //one hundred thousand
    10000000 //ten million
    1000000 //one million

    You KNOW what's going to happen if you depend on comments.
    100000 //one hundred thousand
    

    100000000 //ten million 1000000 //one million

    And to be fair, it's not unique to my style:

    ONE_BILLION = 1000
    TEN_MILLION = 10
    TEN = 1000000
    

    You can screw up any of the listed methods quite easily.

  • (cs) in reply to Evan

    This is true but even if you use -O3 for..

    int main () {static const int ONE=1,TWO=2; printf("%d\n",ONE+TWO); return 0; }

    ..you still get a difference..

        movl    $3, %esi
        movl    $.LC0, %edi
        xorl    %eax, %eax
        call    printf
    

    I'll be the first to admit I know bugger all about x86 asm & I suspect the xorl may be faster that the movl. I also loathe java so I'm glad to see someone who knows their stuff!

    I hope you see my original point, very few people these days understand the consequences of what they're writing. Compiler optimization saves them from having to learn.

  • Kasper (unregistered) in reply to ben
    ben:
    We have seen number-constants many times; under what circumstances do they make sense? (I dont mean e.g. E and PI but ONE, TWO, ...)
    Here is one code example
    const int one = 1;
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
    One of the arguments to setsockopt is defined as a point to a constant value. In C this just means the called function promises not to change the value being pointed to. This doesn't mean that the value has to be declared as a constant in the calling function, but in the case of setsockopt, you really do want it to be a constant.
  • (cs) in reply to Shill
    Shill:
    In some cases the ring might even contain the traditional 1 and 0 and these will NOT correspond to the ring's 1 and 0.

    That's not quite possible. If a ring R contains (a subring isomorphic to) Z where R's arithmetic is an extension of Z's, 0_R will equal 0_Z, since it is equal to (x - x) for any x \in Z, and the subtraction takes place in R and Z simultaneously.

    OTOH if you take 1_Z to be an idempotent element of a commutative ring R then the additive subgroup of R generated by 1_Z will be a subring of R isomorphic to the integers or the integers modulo something. As long as the idempotent isn't equal to 0_R or 1_R and generates an infinite subgroup, this will do the trick.

  • The happy Bunny (unregistered) in reply to faoileag

    why should it be different for programmers? If you don' know the answer, you should not be managing programmers!

  • potato (unregistered)
    snoofle:
    It's not like they could have written:
        public class StringUtils {
          public String stringPrefix(String in, int maxLen){ 
            if (in == null) {
               return null;
            }
            if (maxLen < 1) {
               return "";
            }
            return in.length() <= maxLen
                     ? in
                     : in.substring(0,maxLen);
          } 
        }
    
    Wouldn't this be somewhat better?
    public class StringUtils{	//Apache Commons Lang library already has a class with this name, by the way. TRWTF not using good open source Java libraries (assuming this is Java we're talking here...).
    	public String stringPrefix(String in, int maxLen) throws NullPointerException, IndexOutOfBoundsException{
    		if(in == null){
    			throw new NullPointerException("stringPrefix input String should not be null.");
    		}else if(maxLen == 0){
    			return "";
    		}else if(maxLen < 0 || maxLen > in.length()){
    			throw new IndexOutOfBoundsException("Index " + maxLen + " out of bounds for stringPrefix input String " + in);
    		}
    		return in.substring(0, maxLen);
    }
  • ryan (unregistered)

    Man... if only there were an existing function in the framework that would return the first n characters of a string...

  • River Song (unregistered) in reply to Jeff Grigg
    Jeff Grigg:
    I was on a project where TWO of those Highly Paid Consultants couldn't figure out why their "string copy" function, written in C, wasn't working. They were using an assignment statement (the "=" operator) to assign one function parameter to the other. The debugger seemed to be showing them that their destination parameter had the right string value. They just couldn't figure out why it kept "disappearing" when their "string copy" function returned. I gave them some hints, but they were not listening. Eventually, after a few hours, they figured it out. :-/

    Man... what do I have to do to become a Highly Paid Consultant? Sounds like my kind of job. While my colleagues fight some stupid strdup function, I can read the rest of the Internet and/or contribute some open source code after writing my working and tested solution that I'll present at the end of the day first.

Leave a comment on “Screwing Up the Screw Up”

Log In or post as a guest

Replying to comment #:

« Return to Article