Follow Slashdot blog updates by subscribing to our blog RSS feed

 



Forgot your password?
typodupeerror
×
Bug

Pet Bugs? 1261

benreece asks: "During my few years as a programmer/developer I've come across some strange bugs. Recently I found that Microsoft's VB/VBScript(ASP) round function has problems (for example, 'round(82.845)' returns '82.84' instead of '82.85'). It took me an annoyingly long time to realize the problem wasn't mine. I'm wondering what other obscure, weird, and especially annoying bugs in languages/compilers/etc have frustrated other developers." Memorable bugs. Every developer has one. What were yours?
This discussion has been archived. No new comments can be posted.

Pet Bugs?

Comments Filter:
  • by A nonymous Coward ( 7548 ) on Wednesday June 26, 2002 @03:55PM (#3771692)
    Round to the nearest even digit if the truncated value is .5 Otherwise there's a slight upward bias.
  • Rounding (Score:3, Informative)

    by Ethidium ( 105493 ) <chia_tek@@@yahoo...com> on Wednesday June 26, 2002 @03:56PM (#3771702) Homepage Journal
    Under some rounding schemes, .845 should round to .84

    We all learned in grade school that fives round up, but that doesn't make it preciesely even (there isn't a clean break between same-size sets of integers). So, under some schemes you round a five up if the number preceeding it is odd, down if it's even.

    There are more complex schemes too, nearly all of them leading to a five getting rounded down some of the time.
  • 82.84499 (Score:3, Informative)

    by Coward, Anonymous ( 55185 ) on Wednesday June 26, 2002 @03:58PM (#3771720)
    Floating point numbers have problems with precision, your computer can not store 82.845 in a floating point number so the number it stores is slightly less than 82.845 which VB correctly rounds to 82.84
  • Re:Rounding (Score:3, Informative)

    by jeffy124 ( 453342 ) on Wednesday June 26, 2002 @03:59PM (#3771734) Homepage Journal
    IIRC, IEEE wanted to set the standard to round up one half the time, down the half, resulting in balance. But the IRS and every corporation out there would see that as losing money (a penny was worth something back then), so they opted for always rounding up if the deciding digit was 5.
  • by MSwanson ( 99458 ) on Wednesday June 26, 2002 @04:00PM (#3771754)
    It's not MSDN, but here's a reference:

    http://www.devguru.com/Technologies/vbscript/quick ref/round.html [devguru.com]
  • From MSDN... (Score:3, Informative)

    by bje2 ( 533276 ) on Wednesday June 26, 2002 @04:01PM (#3771765)
    "When you convert a decimal value to an integer value, VBA rounds the number to an integer value. How it rounds depends on the value of the digit immediately to the right of the decimal place--digits less than 5 are rounded down, while digits greater than 5 are rounded up. If the digit is 5, then it's rounded down if the digit immediately to the left of the decimal place is even, and up if it's odd. When the digit to be rounded is a 5, the result is always an even integer." so, Ed is correct...the round function is working to the documentation...
  • Re:Rounding (Score:1, Informative)

    by Anonymous Coward on Wednesday June 26, 2002 @04:04PM (#3771798)
    The standard IEEE 754 rounding mode is round to nearest value with ties broken in favor of the value with low bit 0. So evidently IEEE went with what they wanted.
  • Re: Wrong (Score:1, Informative)

    by Anonymous Coward on Wednesday June 26, 2002 @04:05PM (#3771801)
    Stupid HTML ate my less than sign!

    The mathematic function round is defined as follows:

    f(x) -&gt y
    : x.n &lt x.5 -&gt y=x
    : x.n &gt= x.5 -&gt y=x+1

  • by mojorisin67_71 ( 238883 ) on Wednesday June 26, 2002 @04:10PM (#3771870)
    This was on NT.

    While exiting the program, Microsft
    was unloading the socket DLL before DLL's we had
    created. This caused our program to always crash
    on exit.

    It was obvious due to some internal DLL dependencies,
    NT was choosing a random order
    to unload DLLs.

    We spent months trying to fight with Microsoft,
    but could not get a solution. In the end
    we decided not to support NT as a platform ;-).
  • Re:First ever bug (Score:2, Informative)

    by TheCrazyFinn ( 539383 ) on Wednesday June 26, 2002 @04:15PM (#3771920) Homepage
    Sorry, that's an Urban Legend.

    It was a joke, as the term bug predates the finding of that dead fly.

    Check the Jargon File for details
  • Re:Not a bug (Score:3, Informative)

    by Asprin ( 545477 ) <(moc.oohay) (ta) (dlonrasg)> on Wednesday June 26, 2002 @04:17PM (#3771936) Homepage Journal
    That's not a bug. It's a more accurate way to round off numbers. If you always round 5 up, that means you round 5 out of 9 numbers up, and 4 out of 9 numbers down. This can cause problems if you're rounding lots of numbers.

    NO!!!!!!

    Please don't take this as a flame, because I'm not upset with you, just the ignoramuses that came up with this scheme. This is a stupid way define ROUND(), and I disagree entirely with the justifiction because ROUND() has to be defined in the case that the digit is a zero, right?

    In other words,
    digits 0,1,2,3,4 get rounded DOWN
    digits 5,6,7,8,9 get rounded UP

    See - it's completely even without this odd/even cockamamie bullstuff. In fact, this definition of ROUND() throws off the statistics because it inappropriately weights the UP/DOWN results (either 50/50 or 60/40) based on info that is irrelevant to the ROUND() process.

    It's like the people who coded this function never studied actual math and don't understand that the trivial case (zero) counts!

    I'm sorry, I don't usually go off like this but when something this simple gets this fscked up, it really frosts my wheaties.
  • NT Backspace Bug (Score:3, Informative)

    by rootmonkey ( 457887 ) on Wednesday June 26, 2002 @04:19PM (#3771972)
    One of my all time favorites. Just print too many backspaces and cause the window's machine to croak. Always a crowd pleaser. And the funny thing is it still works today in NT/XP ... Good details here [tesco.net]
  • Re:From MSDN... (Score:2, Informative)

    by Harik ( 4023 ) <Harik@chaos.ao.net> on Wednesday June 26, 2002 @04:20PM (#3771989)
    Yea, as does every financial system in the world.

    Even PHP round() uses odd/even to deal with halves. It's just the Right Way.

  • VS 6.0 getline() bug (Score:3, Informative)

    by wunderhorn1 ( 114559 ) on Wednesday June 26, 2002 @04:21PM (#3771995)
    One pretty annoying bug I've run into is that the getline() function which is part of Standard C++ Library doesn't return when you press Enter.

    http://support.microsoft.com/default.aspx?scid=kb; EN-US;q240015 [microsoft.com]

    Now, I wasted a lot of time, but eventually confirmed on the web that this is a known bug in the Microsoft C++ library which has persisted from Visual Studio 5 into version 6.

    Apparently, the Standard C++ Library used in both products was produced by Dinkumware and they, with their illustrious author/founder P. J. Plauger, were embroiled in a multi-year copyright dispute which made it impossible for them to debug (let alone update) the library. Most of the commenters online seemed to believe that this problem could not be solved and we had to wait for the copyright battle to be resolved (it has).

    My impression is that Microsoft has elected not to provide an update to the library (which includes the STL) until the release of .NET.

  • by coyote-san ( 38515 ) on Wednesday June 26, 2002 @04:21PM (#3772001)
    There are actually something like 4 different IEEE rounding functions. I'm pretty sure this one, "round towards even," is the most commonly used as a default since it introduces the least bias in the results.

    The others, from memory so they may be off, are:

    - round towards zero. (.45 rounds to .4, -.45 rounds to -.4)

    - round towards -infinity (.45 rounds to .4, -.45 rounds to -.5 and thence to -1.0)

    - round towards +infinity (.45 rounds to .5 (and thence to 1), -.45 rounds to .4)

    and possibly round towards infinity (.45 rounds to .5 and thence to 1, -.45 rounds to -.5 and thence to -1), but I'm not sure this mode actually exists since it would tend to inflate values during very long computations.

    You should be able to control the behavior by some obscure function that nobody ever remembers.
  • Re:From MSDN... (Score:3, Informative)

    by quigonn ( 80360 ) on Wednesday June 26, 2002 @04:23PM (#3772026) Homepage
    BTW: this "banker's rounding" as you call it is the method you learn rounding in school in Austria. That's why VBScript's behaviour seems pretty normal to me.
  • Round to even (Score:3, Informative)

    by coyote-san ( 38515 ) on Wednesday June 26, 2002 @04:25PM (#3772049)
    It isn't just the way "your professor" chose to do rounding, "round to even" is the standard practice in science and engineering. He should have made that clearer to the class (or you should have paid better attention. :-)
  • by devphil ( 51341 ) on Wednesday June 26, 2002 @04:26PM (#3772061) Homepage
    Will fix that for you.
  • by Dasein ( 6110 ) <tedc@nospam.codebig.com> on Wednesday June 26, 2002 @04:30PM (#3772113) Homepage Journal
    Actually, your OpenGL implementation is supposed to give you and error back. You have to call glGetError() to get it. In this case it should return GL_STACK_OVERFLOW.

    I know first hand that this works under WindowsXP with the nVidia drivers. Not that the drivers should have anything to do with it.

    As an aside, you should call glGetError() in a loop. There may be multiple errors waiting.

    So either you had a broken OpenGL implementation or just forgot to call glGetError(). Anyway, just thought I'd point out that this isn't a generic OpenGL problem.
  • by bmwm3nut ( 556681 ) on Wednesday June 26, 2002 @04:31PM (#3772123)
    this is a very common issue when working with floating points. you should never check to see if two floating points are equal, unless you mean equal to all precicion. a much quicker way than using sprintf is this:
    #define EPSILON 1e-6 //or what ever tolerance you want

    float x,y
    //do stuff with x and y

    if (fabs(x-y)<EPSILON)
    {
    //x and y are equal
    }
    else
    {
    //x and y are unequal
    }
  • Re:From MSDN... (Score:1, Informative)

    by Anonymous Coward on Wednesday June 26, 2002 @04:34PM (#3772157)
    "If you're trying to find the difference of a series of numbers", THEN WHY ARE YOU ROUNDING THEM FIRST?
  • by spitzak ( 4019 ) on Wednesday June 26, 2002 @04:35PM (#3772174) Homepage
    No, try comparing the sets of values the change. The set of values that changes by rounding down (in .5 goes to 1 rounding) is (0,.5) and the set that is changed by rounding up is [.5,1). The rounded-up set has one extra number, .5. You tried to balance this by adding .0 to the lower set, but you should have added 1 to the upper set in that case.

    In fixed point binary the rint() (and MS Basic) behavior is necessary to avoid drift. Imagine a simple fixed-point that can only do integers and .5. It should be obvious that user the round-up scheme 2/3 of the numbers (the integers) do not change and 1/3 (the .5's) do change by .5. Thus the average drift is +1/6. In the rint() behavior, 2/3 of the numbers do not change, 1/6 round up by .5, and 1/6 round down by .5.

  • by novas007 ( 411673 ) on Wednesday June 26, 2002 @04:37PM (#3772200) Homepage
    I've had that problem before, but it's not what you think (i think). Do you use zsh? Some shells, including zsh, protect their prompt. So if you print a single line w/o a \n, the prompt overwrites it, and you never see it. I think that bash by default will just print the prompt after whatever it was you printed. Try piping it to less or something, and you'll see it IS actually there :)
  • by mcc ( 14761 ) <amcclure@purdue.edu> on Wednesday June 26, 2002 @04:38PM (#3772213) Homepage
    Oh, crud, it's still there.. Yeah. Sorry. I didn't notice, but here it is: the several active discussions page [slashdot.org]. These days it seems to mostly link to slashdot journals. Sorry, i somehow missed it when i was writing the parent post. I feel dumb.

    I really, really hope this is something that the /. crew doesn't mind me bringing attention to. I just think it's cool :)
  • by spitzak ( 4019 ) on Wednesday June 26, 2002 @04:39PM (#3772226) Homepage
    No, look at the range that goes to an integer when centered on an integer:

    5678901234

    Yes there are 10 numbers that go to each integer, but they go to the '0' location in the above range. It should be obvious that the '0' is not in the middle but slightly to the right.

    The rint() solution is to alternate sets of 11 and 9 numbers for each integer:

    56789012345

    678901234

    In this case the 0 is centered in each set, so there is no drift of the average.

  • by Mr Z ( 6791 ) on Wednesday June 26, 2002 @04:42PM (#3772252) Homepage Journal

    There is no "proper" way to reduce the precision of a number under all circumstances. Each method of rounding or truncating 0.5 has its own pitfalls:

    • Round-to-even, aka. banker's rounding. This is probably the best, since it distributes errors uniformally so as to not cause a long-term average bias. It's also very expensive to calculate as compared to the alternatives.
    • Round (pseudo)randomly. Add an infintesimally small random or pseudo random bias to numbers that end in 0.5. This has the same bias properties as round-to-even, but with less predictability. If the biasing function is just a simple hash of the other bits of the number, though, then at least it's deterministic.
    • Round-towards-zero. (I believe this is sometimes called "unbiased rounding".) For numbers uniformally distributed around zero, this form of rounding tends to also have no long-term average bias. The average magnitude is biased, though, towards smaller magnitudes.
    • Round-towards-plus-infinity. (aka. "rounding up", or sometimes just "rounding".) This is the rounding they usually teach you in grade school -- round 0.5 up. (At least, that's what they taught me until I got to high-school.)
    • Round-towards-minus-infinity. (aka. "rounding down" or "truncation".) This is what you get when you always round down. Right-shifting 2s complement numbers (with sign extend) typically gives you this form of rounding. One nice side effect is that the bias is uniform and so can be made to cancel in some cases elsewhere in your calculation. This technique has the advantage of being the cheapest -- you just throw away bits.

    So, as you can see, there's no right way per se. It just depends on what you're doing.

    --Joe
  • by Violet Null ( 452694 ) on Wednesday June 26, 2002 @04:47PM (#3772312)
    The reason for this is that nobody seems to believe that .0 is a valid rounding value

    In your words: That's nonsense. Of course .0 is a valid rounding _value_. But .0 isn't rounding _down_. Therefore, over a large number of roundings, you will build up an upward difference.

    Consider one decimal point precision (for simplicity's sake), using your idea that .5 always rounds up.

    .0 => 0. Difference = 0.0

    .1 => 0. Difference = -0.1

    .2 => 0. Difference = -0.2

    .3 => 0. Difference = -0.3

    .4 => 0. Difference = -0.4

    .5 => 1. Difference = 0.5

    .6 => 1. Difference = 0.4

    .7 => 1. Difference = 0.3

    .8 => 1. Difference = 0.2

    .9 => 1. Difference = 0.1

    Sum difference: 0.5
  • Re:From MSDN... (Score:3, Informative)

    by bje2 ( 533276 ) on Wednesday June 26, 2002 @04:51PM (#3772362)
    looking at this chart, it should be fairly obvious...the first number is the decimal, and the second number is the difference between the 'real' number and the 'rounded' number if we used your system...since the .0 had no contribuition (no difference between real and roudned), you'll see that the digits [0-4] contribute a difference of 1, while the digits [5-9] contribute a difference of 1.5 for this reason, the digit 5 is split up between rounding up and rounding down...

    .0 .0
    .1 .1
    .2 .2
    .3 .3
    .4 .4
    .5 .5
    .6 .4
    .7 .3
    .8 .2
    .9 .1
  • Re:From MSDN... (Score:4, Informative)

    by kallisti ( 20737 ) <rmidthun@yahoo.com> on Wednesday June 26, 2002 @04:59PM (#3772458) Homepage
    There are 10 digits [0-9], and [0-4] rounds down, while [5-9] rounds up. That means there are 5 digits that will round down and five that will round up,


    The flaw in your reasoning is that you consider all the "round downs" to be the same. What you really need to do is to total the error:

    0: no error

    1: -1

    2: -2

    3: -3

    4: -4

    5: to be determined

    6: +4

    7: +3

    8: +2

    9: +1

    Right now, without the 5 everything balances out, so the average error for 5 must be zero. Since it is either +5 or -5, then you must have an equal number of ups and downs, this rounding method is the easliest way to do that.

  • by ComputerSlicer23 ( 516509 ) on Wednesday June 26, 2002 @05:08PM (#3772555)
    I see what you're driving at, however the case of .5 below is discussing something akin signficant figures, which I'll concede act differently. If you're saying that because they are floating point numbers and a computer can't work with them perfectly, hmmm, if I wanted that kind of precision I'd write my own library.

    As to the point of including 1 in the upper set is faulty. When rounding you must divide up the set [0,1). You don't have the 1 to distribute. The way to equally distribute the numbers from [0,1) is the one previously described. The fact that the 0 doesn't change is irrelavent to me. In the case you desribed above, you must deal with distributing {0, 0.5} into two cases, there 0->1 and .5 -> 1 everything else falls out. You're double counting when you generate the number. 0 is 1 in the next case. Here an example should show it. All the cases betweeen 0 and 10:

    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 stay the same.

    Rounding 0.5, 1.5, 2.5, 3.5, 4.5, 6.5, 7.5, 8.5, 9.5 to 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 has slight skew because 0 should occur twices.

    That's just a boundary problem. However, extend that out from 10 to infinity and go to negative infinity and it all comes out in the wash, and you're system doesn't. Yours should come out with: 0, 2, 2, 4, 4, 6, 6, 8, 8, 10.

    There is internal skew towards even numbers. My system has absolutely no skew towards any numbers in the global sense on the set of all integers. The problem with you're analysis is that you say I go towards 1 to much, but the 1 in this case is the 0 in the next case, so it all balances out.

    If I had mod points, you'd get +1 informative. The explaintion is clear, and now I understand what why people do think that, I just politely disagree now.

    Thanks, Kirby

  • by tomhudson ( 43916 ) <barbara,hudson&barbara-hudson,com> on Wednesday June 26, 2002 @05:26PM (#3772751) Journal
    I remember how Computer Associates had both color and colour in their clipper include files, so you could use either one.

    I thought it was pretty neat.

    On the other hand, in c you could have just done the following:

    #define colour color

    another useful shortcut is to do this:

    #define str chr* #define strs chr**

    int main(int argc, strs argv, str env)

    helps remove a few bugs from code you write.

  • by Quietust ( 205670 ) on Wednesday June 26, 2002 @05:48PM (#3773040) Homepage
    Actually, the current HTML spec (4.01) states that </TH> [w3.org], </TD> [w3.org], and </TR> [w3.org] are all optional.
  • by Wraithlyn ( 133796 ) on Wednesday June 26, 2002 @06:14PM (#3773479)
    Check out the Mersenne Twister [keio.ac.jp], it's beautiful. Here's a couple points from that page:

    • Far longer period and far higher order of equidistribution than any other implemented generators. (It is proved that the period is 2^19937-1, and 623-dimensional equidistribution property is assured.)
    • Fast generation. (Although it depends on the system, it is reported that MT is sometimes faster than the standard ANSI-C library in a system with pipeline and cache memory.)
    • Efficient use of the memory. (The implemented C-code mt19937.c consumes only 624 words of working area.)


    There are implementations in C, Java, PHP, Fortran, Excel (I assume VBA) and probably others.

    I only have experience with the Java impl, and it is very good. There are two classes, MersenneTwister, which is a true descendant of java.util.Random, and there is also a MersenneTwisterFast class, which does NOT inherit from Random (same public methods, and identical algorithm though), but clocks in at about twice the speed, due to tricks like avoidance of synchronization, and method inlining and finalizing.
  • Re:From MSDN... (Score:1, Informative)

    by Anonymous Coward on Wednesday June 26, 2002 @06:28PM (#3773641)

    But if you are rounding, you cant base your error on just the one digit. You have to consider all the digits following it as well. There is a big difference between .5 and .599999999999 for instance. Its a range, so the error in the rounding is also a range of possble error.

    So, if you are starting with real numbers, the actual error would be as follows:

    0: 0.0000001 - 0.9999999
    1: 1.0000001 - 1.9999999
    2: 2.0000001 - 2.9999999
    3: 3.0000001 - 3.9999999
    4: 4.0000001 - 4.9999999
    5: either 5.0000001 - 5.9999999 or 4.0000001 - 4.9999999 depending on MS
    6: 3.0000001 - 3.9999999
    7: 2.0000001 - 2.9999999
    8: 1.0000001 - 1.9999999
    9: 0.0000001 - 0.9999999

    the digit 5 really is in the center, but only if all the digits *after* 5 are 0.

    A real world example: The number 2.595745 really *is* closer to the integer 3 than it is to 2, and should be rounded accordingly.

  • by jeffy124 ( 453342 ) on Wednesday June 26, 2002 @06:36PM (#3773736) Homepage Journal
    this is a guess...

    the back-slash \ at the end of the line indicates to the compiler that the following line is to be considered part of the current line, meaning the compiler (iirc, lexical analyzer) will translate the above to the following:

    #include

    // tom 7 was here - 1998 \typedef unsigned char uchar;
    int something(uchar c);

    or more precisely--

    --preprocessed contents of stdio.h--
    int something(uchar c);

    so the "bug" (actually a compile-time error) is an undefined token 'uchar,' unless of course, uchar has a definition in stdio.
  • by g4dget ( 579145 ) on Wednesday June 26, 2002 @06:36PM (#3773737)
    Implicit in that kind of reasoning is the assumption that digits to be rounded are distributed uniformly (at least in the limit). This is probably not the case for most real data; c.f. Benford's law for first digit distributions.

    Round-to-even is another one of those misfeatures that have crept into modern floating point standards without much justification.

  • Re:From MSDN... (Score:3, Informative)

    by kallisti ( 20737 ) <rmidthun@yahoo.com> on Wednesday June 26, 2002 @07:14PM (#3774211) Homepage
    The number 2.595745 really *is* closer to the integer 3 than it is to 2, and should be rounded accordingly.

    You bring up a good point. If we really were looking at real numbers it wouldn't be an issue since you never get an exact .5, but we're dealing with computers.

    If you are rounding off one digit, I gave the values for summing a series in another post (banker's was exact, round up too high). I modified the program to round two digits and found that banker's rounding was short exactly as much as round up was ahead. For more than two digits, the banker error gets much worse, as would be expected. You should only use banker's rounding exactly on the half interval.

    IEEE defaults to round to nearest, and I believe that in the case of midpoints it selects based on the low bit, this would be banker's rounding with the changes you noted. I had a hard time finding a good explanation of IEEE 754 in a quick Google search.
  • My Favortie Bug (Score:2, Informative)

    by Type11 ( 579651 ) on Wednesday June 26, 2002 @08:53PM (#3775168) Homepage
    Was having some really bizzare problems with our String class being used in a stl vector and ended up having to trace it into the RougeWave HP stl. It was in vector<_TypeT,_Allocator>::operator= (const vector<_TypeT,_Allocator>& __x)
    below is the change for anyone who might have hit this or runs this setup. Hope it can help someone avoid it and all the time it wasted. Just love problems in the STL! *** are the two lines changed.

    *** _C_end_of_storage = _C_finish = _C_start + __x.size();
    }
    else { // size() < _x.size() < capacity()
    // advance this->end () first
    *** _C_end_of_storage = _C_finish = _C_start + __x.size ();

    Changed To:

    *** _C_finish = _C_start + __x.size();
    }
    else { // size() < _x.size() < capacity()
    // advance this->end () first

    copy (__x.begin (), __x.begin () + size (), begin ());

    // write past original value of this->end ()
    uninitialized_copy (__x.begin () + size (), __x.end (),
    begin () + size (),
    _RWSTD_VALUE_ALLOC_CAST (*this));
    }

    *** _C_end_of_storage = _C_finish = _C_start + __x.size ();

    This of course was becuase _C_end_of_storage should not have been set before the calling of size() as it would be incorrect.

He has not acquired a fortune; the fortune has acquired him. -- Bion

Working...