C# 在尝试规范化数据时出现了巨大的数值错误

C# 在尝试规范化数据时出现了巨大的数值错误,c#,math,statistics,average,numerical-methods,C#,Math,Statistics,Average,Numerical Methods,我经常用程序处理一些数据,而不是用数据。简单来说,让我们考虑数据是一串相同数量的数字。 当数字过高时,对数据进行规范化可能是有用的。常见的转换之一是从所有值中减去平均值。此转换后,转换后的数据的平均值为零 在平均值为零后可以进行的其他常见转换是将数据除以它们的标准偏差。应用此转换后,新数据具有单位方差 当以这种方式处理标准化的数据时,我希望数值误差应该更小。然而,我似乎无法进行这些转换,因为即使在我试图计算标准偏差时,数值误差也会出现 下面是c#中的示例代码,我试图计算标准偏差。即使没有(公式)

我经常用程序处理一些数据,而不是用数据。简单来说,让我们考虑数据是一串相同数量的数字。 当数字过高时,对数据进行规范化可能是有用的。常见的转换之一是从所有值中减去平均值。此转换后,转换后的数据的平均值为零

在平均值为零后可以进行的其他常见转换是将数据除以它们的标准偏差。应用此转换后,新数据具有单位方差

当以这种方式处理标准化的数据时,我希望数值误差应该更小。然而,我似乎无法进行这些转换,因为即使在我试图计算标准偏差时,数值误差也会出现

下面是c#中的示例代码,我试图计算标准偏差。即使没有(公式)的统计知识,也很容易看出程序的输出应该为零。(如果数据是常数数组,则数据平方的平均值等于平均值的平方。)

程序输出的不是零,而是由数字错误引起的巨大数字:2133383.0308878

请注意,如果我省略Math.Sqrt(即,我将计算方差而不是标准偏差),那么误差将高得多


原因是什么?我该如何用smaler数字错误来写呢?

我认为您混淆了可能的最大/最小值(±5.0×10)−324至±1.7×10308),有效位数可用(15-16)为双精度


在你的例子中,我认为你没有首先缩放输入,这是在浪费数字,也就是把你的值转换成1.47834,数值计算的比例因子为1/10^7。

尽管用于方差的公式在数学上是正确的(即如果精度无限),但它可能会导致有限精度的问题

对于N数据X,更好的方法是计算

variance = Sum{ square( X[i] - mean) }/ N
在哪里

如前所述,这需要两次通过数据。如果这是尴尬的,你实际上可以在一次通过它。您需要保留三个变量,n(到目前为止看到的数据项的数量)均值和方差。这些都应初始化为0(也称为0.0)。然后,当您获得下一个数据项x时:

n = n + 1
f = 1.0/n
d = x-mean
mean = mean + f*d
variance = (1.0-f)*(variance + f*d*d)

在处理数据项n后的每个阶段,平均值、方差实际上是到目前为止数据的计数、平均值和方差。

Thx获得最佳答案。我特别喜欢你一次完成的方式。我理解这个意思是正确的。然而,方差公式在我看来似乎是错误的。那么下面的公式呢<代码>方差=(1.0-f)*方差+f*d*d*(1.0+f)这对我来说更有意义。我很确定我的公式是正确的。不能在第一个数据项之后计算,当f=1时,公式给出一个非零值,2*d*d,其中d是第一个数据值(因为平均值初始化为0)。但是一个集合的方差是0。你的反例是对的。你的公式也是如此。我用你的公式编写了程序,它会返回期望值。所以我把你的答案标记为接受。然而,我仍然不明白它为什么会起作用。在我看来,使用这种方法,你仍然会遇到大整数的问题:第一次计算d*d(“mean”是零,所以你有x*x),你可能会导致一个巨大的错误。稍后,如果平均值变化过大,这也会造成麻烦。有效数字的数量应事先指定,输入数据应相应缩放,以确保结果可靠。冈萨雷斯:第一次迭代的方差是(1.0-f)*。。。它等于0,因为f是1/1。缩放与此无关。无论如何,它是由FP表示完成的,可以被分解,也可以不分解。
mean = Sum{ X[i] } /N
n = n + 1
f = 1.0/n
d = x-mean
mean = mean + f*d
variance = (1.0-f)*(variance + f*d*d)