当前位置: 首页 > 知识库问答 >
问题:

略有不同的浮点数学结果(C到golang)

赵英范
2023-03-14

我正致力于直接在戈朗开发一个技术指标库。除其他外,这是学习戈朗语的练习。

我一直在验证我的算法的结果,方法是用TA-Lib(或者更确切地说是TA-Lib的ruby包装器)生成的数据构建测试用例。

上面的问题涉及浮点数学的一个非常简单的表现形式。很难确认一段较长的代码是否真的解决了这个问题。

我如何确认它只是浮点数学的变体,因为顺序?

/结束编辑

package ta

import (
  "math"
)

func BollingerBands(values []float64, period int) ([]float64, []float64, []float64) {
  deviationsUp := 2.0
  deviationsDown := 2.0

  middleBand := Sma(values, period)
  offset := len(values)-len(middleBand)
  var upperBand []float64
  var lowerBand []float64
  for idx, v := range middleBand {
    backIdx := offset+idx-period+1
    curIdx := offset+idx+1
    if backIdx < 0 {
      backIdx = 0
    }
    stdDev := SliceStdDev(values[backIdx:curIdx])
    upperBand = append(upperBand, v + (stdDev * deviationsUp))
    lowerBand = append(lowerBand, v - (stdDev * deviationsDown))
  }
  return upperBand, middleBand, lowerBand
}

// Sma produces the Simple Moving Average for the
// supplied array of float64 values for a given period
func Sma(values []float64, period int) []float64{
  var result []float64
  for index,_ := range values {
    indexPlusOne := index+1
    if(indexPlusOne>=period) {
      avg := Mean(values[indexPlusOne-period:indexPlusOne])
      result = append(result, avg)
    }
  }
  return result
}

// SliceMean returns the Mean of the slice of float64
func SliceMean(values []float64) float64 {
  var total float64=0
    for _,element := range values {
        total += element
    }
  return total / float64(len(values))
}

// SliceVariance returns the variance of the slice of float64.
func SliceVariance(values []float64) float64 {
    if 0 == len(values) {
        return 0.0
    }
    m := SliceMean(values)
    var sum float64
    for _, v := range values {
        d := v - m
        sum += d * d
    }
    return sum / float64(len(values))
}

// SliceStdDev returns the standard deviation of the slice of float64.
func SliceStdDev(values []float64) float64 {
    return math.Sqrt(SliceVariance(values))
}
require 'indicator/mixin'
x = [26.0, 54.0, 8.0, 77.0, 61.0, 39.0, 44.0, 91.0, 98.0, 17.0]
y = x.indicator(:bbands_5)
# {:out_real_upper_band=>[94.9256473059929, 94.50588827974477, 92.12752961253167, 101.58367006802709, 114.64331379078678, 120.58088881180323, nil, nil, nil, nil] <SNIP>}

共有1个答案

郎经纶
2023-03-14

我觉得算法是不一样的。例如方差:

/* Do the MA calculation using tight loops. */
/* Add-up the initial periods, except for the last value. */
periodTotal1 = 0;
periodTotal2 = 0;
trailingIdx = startIdx-nbInitialElementNeeded;

i=trailingIdx;
if( optInTimePeriod > 1 )
{
   while( i < startIdx ) {
      tempReal = inReal[i++];
      periodTotal1 += tempReal;
      tempReal *= tempReal;
      periodTotal2 += tempReal;
   }
}

/* Proceed with the calculation for the requested range.
 * Note that this algorithm allows the inReal and
 * outReal to be the same buffer.
 */
outIdx = 0;
do
{
   tempReal = inReal[i++];

   /* Square and add all the deviation over
    * the same periods.
    */

   periodTotal1 += tempReal;
   tempReal *= tempReal;
   periodTotal2 += tempReal;

   /* Square and add all the deviation over
    * the same period.
    */

   meanValue1 = periodTotal1 / optInTimePeriod;
   meanValue2 = periodTotal2 / optInTimePeriod;

   tempReal = inReal[trailingIdx++];
   periodTotal1 -= tempReal;
   tempReal *= tempReal;
   periodTotal2 -= tempReal;

   outReal[outIdx++] = meanValue2-meanValue1*meanValue1;
} while( i <= endIdx );

看起来不像你的差异。如果您要复制这些算法,使它们执行完全相同的操作,那么Go版本应该会产生相同的结果。Go只是在做标准的IEEE 754浮点运算。

至于“秩序重要吗?”绝对是这样。由于浮点算术是不精确的,您将丢失信息,因为您做计算。大多数时候,它并没有太大的区别,但有时算法可能非常容易受到这些变化的影响。(所以用代数的方法重新排列你的公式可能不会得到真实代码中相同的答案)

double
FUNCTION (gsl_stats, mean) (const BASE data[], const size_t stride, const size_t size)
{
  /* Compute the arithmetic mean of a dataset using the recurrence relation 
     mean_(n) = mean(n-1) + (data[n] - mean(n-1))/(n+1)   */

  long double mean = 0;
  size_t i;

  for (i = 0; i < size; i++)
    {
      mean += (data[i * stride] - mean) / (i + 1);
    }

  return mean;
}

经常使用的一种解决方案是在非常小的数字(math.abs(expected-result)<,其中定义:const=0.0000001)内进行相等比较,而不是使用==

 类似资料:
  • 我正在使用neo4j来计算一个数据集上的一些统计数据。为此,我经常在浮点值上使用sum。我得到不同的结果取决于环境。例如,执行以下操作的查询: 差别很小(与)。但使简单的等式检查失败就足够了。另一个例子是数据库的不同实例,使用相同的加载过程加载相同的数据可能会产生相同的问题(dbs可能不是1:1,某些关系的加载顺序可能不同)。我取了neo4j求和的原始值(通过简单地移除),并验证它们在所有情况下都

  • 问题内容: 我知道浮点数学充其量可能很难看,但我想知道是否有人可以解释以下怪癖。在大多数编程语言中,我测试了0.4到0.2的添加会产生轻微的错误,而0.4 + 0.1 + 0.1会给出非错误。 计算不均的原因是什么,人们可以在相应的编程语言中采取什么措施以获得正确的结果。 在python2 / 3中 在Julia 0.3中也是如此 和Scala: 和Haskell: 但是R v3正确了: 问题答案

  • 我知道浮点数学充其量是很难看的,但我想知道是否有人能解释下面的怪癖。在我测试的大多数编程语言中,将0.4加到0.2会产生轻微的误差,而0.4+0.1+0.1则表示不存在。 这两种计算结果不相等的原因是什么?在各自的编程语言中可以采取什么措施来获得正确的结果。

  • 问题内容: 执行以下代码时: 显示以下输出: 1.0000001 但是输出应该是 1.0000000 ,对吧?如我错了请纠正我..!! 问题答案: 对于IEEE 754标准,0.1并不是真正的“ 0.1”。 0.1编码为:(带有浮点数) 0是符号(=正) 01111011指数(= 123-> 123-127 = -4 (127是IEEE 754中的 偏差 )) 100110011001100110

  • 问题内容: 5年前关闭。 我必须将两个整数相除并得到一个浮点数作为我的代码: 我用调试器检查值 为什么结果为0.0?我应该怎么做才能获得正确的浮动? 问题答案: 当您将两个数相除时,将执行整数除法,在这种情况下,将导致22/64 =0。只有完成此操作后,您才能创建一个。和的表示是。如果要执行浮点除法,则应 在 除法 之前进行 强制转换:

  • 几年前,在20世纪90年代初,我创建了图形包,用于优化基于定点算术的计算,并预先计算出了cos、sin和sqrt和log近似的缩放方程的表格,这些表格使用牛顿近似法。这些先进的技术似乎已经成为图形和内置数学处理器的一部分。大约5年前,我上了一堂数值分析课,涉及到一些古老的技术。我已经编码了近30年,很少看到那些老的定点优化在使用,即使在为世界级粒子加速器实验的GPGPU应用工作之后。固定点方法是否