views:

47

answers:

2

In the Silverlight Toolkit there is this method:

    /// <summary>
    /// Removes the noise from double math.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <returns>A double without a noise.</returns>
    internal static double RemoveNoiseFromDoubleMath(double value)
    {
        if (value == 0.0 || Math.Abs((Math.Log10(Math.Abs(value)))) < 27)
        {
            return (double)((decimal)value);
        }
        return Double.Parse(value.ToString(CultureInfo.InvariantCulture), CultureInfo.InvariantCulture);
    }

I don't understand what the purpose is, is there noise in doubles from doing math in .Net?

What is with the cast double to decimal to double?

Why do a ToString the Parse?

I wrote a quick test project to generate some random numbers and run it through the method and I didn't see any changes (not that I thought that I would).

+1  A: 

What this tries to do is to mitigate the rounding difference inherit to floating point arithmetic.

If you for example take the following snippet:

double result = 1.0 / 7.0;

double difference = result - RemoveNoiseFromDoubleMath(result);

Console.WriteLine(difference);

This produces a difference of -1,38777878078145E-16.

Pieter
That makes sense in that the Toolkit is using the method around a double calculation: ValueHelper.RemoveNoiseFromDoubleMath(ValueHelper.RemoveNoiseFromDoubleMath(Math.Floor(typedValue / typedInterval)) * typedInterval);
darren
A: 

It's really awesome that this function has a comment block that actually doesn't explain what this "noise" it's trying to deal with actually is, and how it affects the value.

The way I read it, if the number has less than 27 base-10 digits (or is exactly zero), it gets converted to a decimal, then back to double. I would have expected the conversion to decimal should have no effect on the value, since decimal has greater resolution than double. Converting back to double should again be lossless.

Pieter's example shows that this operation actually does appear to affect the value, so apparently conversions from double to decimal and back aren't value-preserving, even when they could be. Looking into msdn, I see this: http://msdn.microsoft.com/en-us/library/yht2cx7b(v=VS.80).aspx

which says:

When you convert float or double to decimal, the source value is converted to decimal representation and rounded to the nearest number after the 28th decimal place if required.

Okay, so it rounds. This means that if you have a double with a value of 1.9999999999999999999999999999, the conversion to decimal will round it up to 2, so when it gets converted back to a double, you get a double with a value of exactly 2.0.

If the number has more than 27 digits, it gets converted to a string, then parsed. I'm not sure what the end result of that is - it would depend on the default behavior of ToString and Double.parse.

Mark Bessey