奇怪的数值误差

时间:2015-07-22 16:49:01

标签: c# mean numerical

我正在实现一个简单的双态粒子滤波器。如果您不知道粒子滤波器是什么,那很好 - 短版本是我需要计算权重在0和1之间的加权平均值,以及0到1之间的值。每个粒子都有一个价值和重量。

然而,C#给了我绝对奇怪的数值问题。

在尝试调试时,这就是我的代码:

            ConcurrentBag<Particle> particles; //this is inputted as an argument to my function
            double mean = 0.0;
            double totalWeight = 0.0;
            foreach (Particle p in particles)
            {
                mean += p.Value * p.Weight;
                totalWeight += p.Weight;

                if (p.Value > 1.01 || p.Weight > 1.01)
                {
                    Console.WriteLine("Value " + p.Value);
                    Console.WriteLine("Weight " + p.Weight);
                    Console.WriteLine("wtf");
                }
            }

            if (totalWeight == 0.0)
            {
                //in this case, everything has miniscule weight, so let's just return 0.0 to avoid this precision corner case.
                return new Bernoulli(0.0);
            }
            double oldMean = mean;
            mean /= totalWeight;
            return mean;

if语句与&#34; wtf&#34;是出于调试目的,它是否被触发。但是,打印输出是:

值1.0 重量0.01

这个if语句根本不应该是真的!发生了什么事?

编辑:关于调试的一点点更新。这是我目前的整个功能:

public override IDistribution createDistribution(ConcurrentBag<Particle> particles)
        {
            if (particles.Count == 0)
            {
                throw new Exception("Cannot create Distribution from empty particle collection");
            }
            if (!particles.ToArray()[0].GetType().IsAssignableFrom(typeof(BinaryParticle)))
            {
                throw new Exception("Cannot create Bernoulli Distribution from non-Binary Particle");
            }

            decimal mean = 0.0m;
            decimal totalWeight = 0.0m;
            foreach (Particle p in particles)
            {
                mean += (decimal)(p.Value * p.Weight);
                totalWeight += (decimal)p.Weight;


                    if ((p.Weight > 1.01))
                    {
                        {
                            Console.WriteLine("Value " + p.Value);
                            Console.WriteLine("Weight " + p.Weight);
                            Console.WriteLine("Value " + p.Value.ToString("0.0000000"));
                            Console.WriteLine("wtf");
                        }
                    }


            if (totalWeight == 0.0m)
            {
                //in this case, everything has miniscule weight, so let's just return 0.0 to avoid this precision corner case.
                return new Bernoulli(0.0);
            }
            decimal oldMean = mean;
            mean /= totalWeight;

            try
            {
                return new Bernoulli((double)mean);
            }
            catch (Exception e)
            {
                decimal testMean = 0.0m;
                decimal testTotalWeight = 0.0m;
                Console.WriteLine(e);
                foreach (Particle p in particles)
                {
                    testMean += (decimal)(p.Value * p.Weight);
                    testTotalWeight += (decimal)p.Weight;
                    Console.WriteLine("weight is " + p.Weight);
                    Console.WriteLine("value is " + p.Value);
                    Console.WriteLine("Total mean is " + testMean);
                    Console.WriteLine("Total weight is " + testTotalWeight);
                }


                Console.WriteLine(testMean / testTotalWeight);
                throw new Exception();
            }
        }

&#34;平均&#34;给出的值与在catch块中的writeline中打印的值不同。我不知道为什么。而且,奇怪的是,它是重量&gt;当重量为0.01时,1.01是真实条件。

1 个答案:

答案 0 :(得分:2)

好的,你们会生气,所以让我先说对不起: - )

问题实际上是一种竞争条件,并且与我对C#中的锁定如何工作的误解有关。我锁定了一个对象,其实例可能会以不同的方式改变,其中粒子包正在改变。用专用的锁定对象替换它可以解决我的问题。

抱歉^ _ ^ ;;