Share via


Spot the Bug

Ran into this recently and thought it might be interesting.

Can you try and spot the bug and the possible error that can occur with the following lines of code?

Decimal randomDoubleAsDecimal()
{
      Random rand = new Random();
      return Decimal.Parse(rand.NextDouble().ToString());
}

Solution in the next post.

Comments

  • Anonymous
    January 23, 2005
    Any relation to this?

    http://www.hanselman.com/blog/PermaLink,guid,bb01694d-d637-45fd-8e82-406dd3bc3027.aspx
  • Anonymous
    January 23, 2005
    The comment has been removed
  • Anonymous
    January 23, 2005
    The comment has been removed
  • Anonymous
    January 23, 2005
    Hmm.. doesn't Random() use the current timestamp as a seed as default?

    If so, then the randomDoubleAsDecimal method might return the same numbers if it's called for example in a for loop, since it's not guaranteed that the timestamp changes between calls?

    Also, isn't Decimal.Parse() Culture dependant, like almost all Parse() functions? Then again, maybe Double.ToString() always returns a compatible format for Parse() functions?
  • Anonymous
    January 23, 2005
    seed values? doesn't that determine the return type as Int32 or Double?
  • Anonymous
    January 23, 2005
    Seed value - wrong direction.

    Format/Culture direction - Getting Warmer - but still not there.

    You will run into the bug even if you use Decimal.Parse.

    NumberFormatInfo numFormat = CultureInfo.CurrentCulture.NumberFormat;

    str = rand.NextDouble().ToString(numFormat);
    dec = Convert.ToDecimal(str, numFormat);

    Next hint will be the type of exception.
  • Anonymous
    January 23, 2005
    Ahh, think i got it.. doesn't Double have a lot bigger range than Decimal? Decimal even though it's a 128bit number has a small range but a larger amount of significant digits.
  • Anonymous
    January 23, 2005
    It's possible that rand.NextDouble().ToString() return number in scientific format in which Decimal.Parse cannot parse. It happens when Random.NextDouble return relatively small number such as 0.00000013241... double.ToString() will return "1.3241E-07" that causes Decimal.Parse to throw FormatException.
  • Anonymous
    January 23, 2005
    Stefán Jökull Sigurðarson's comment may not be valid as Random.NextDouble would return number that is between 0.0 and 1.0 only [0.0,1.0)
  • Anonymous
    January 23, 2005
    Decimal.Parse doesn't mention any exponent part, so I think a FormatException is possible.

    BUT, on the other hand, NextDouble gives only the range 0.0 to 1.0, so one could argue that this would not happen. But, it will happen if the value is close enough to zero. I think this is the answer.
  • Anonymous
    January 23, 2005
    When you use the code defined above with the NumberFormat, you will get 15 digit decimal always as a result. As we all know, decimal holds up to 29 decimal digits precision. Its not an error to get only 15 digits but its an interesting observation.

    Also lets say that you want more digits and your using the System.Globalization.NumberFormatInfo numFormat = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;

    Then if you make a call to numFormat.NumberDecimalDigits = 29; in order to set the precision, then it will thrown an InvalidOperationException. Now when you look at the documentation it says that you can perform set and get on this particular parameter. Again, an interesting twist. Of course maybe its just my ignorance talking. :-)
  • Anonymous
    January 23, 2005
    oh my bad. I didn't see the double there. Of course Double gives you up to 15 digits precision and thats why you get the 15 digits.
  • Anonymous
    January 23, 2005
    Intersting.. I called the function a number of times sequentially and it gave me this.

    0.922284546737692
    0.281089573763818
    0.281089573763818
    0.281089573763818
    0.281089573763818
    0.281089573763818
    0.281089573763818
    0.281089573763818

    Not totally Random is it. :-)
  • Anonymous
    January 23, 2005
    Nat: You're right. I had forgot that Random.NextDouble returns a number between 0.0 and 1.0. Thanks for setting me straight :)

    Sushant: That's what i meant with my random seed comment a little above :). If you call this function in a for loop it will propably return the same number a number of times. That isn't the bug however since that won't throw an exception.

    I'm still thinking hard about this one and trying not to use google or the .NET docs, it makes it more interesting :)
  • Anonymous
    January 23, 2005
    Bingo!

    And the winner is Nat! :)

    Good work guys with all the thought poured in. Will write up an explanation in another post - but Nat got the crux of it.
  • Anonymous
    January 23, 2005
    Hehe. I knew it had to do with precision. Nice catch Nat!!!! If the number is too small, its gonna thrown an exception with the Parse().
  • Anonymous
    March 05, 2006
    also in low memory situations an nullpointer exception will be thrown.
  • Anonymous
    September 22, 2006
    I have 7,850 and I need to save 7,850, not 7,85