go-extend: github.com/thinkeridea/go-extend/exatomic Index | Files

package exatomic

import "github.com/thinkeridea/go-extend/exatomic"

Package exatomic 实现了 float32 与 float64 原子操作, 我在历史项目中实时在线统计一些价格,在多线程时往往非常有用, 简化程序逻辑,并提升程序性能。

float 原子操作可以设计很多个版本,历史项目中我用过 3 种不同的实现方式, 当前项目是我最满意的版本,对程序没有任何入侵,也没有定义新的类型,保持和标准库一致的接口,非常的简单。

使用该包你必须了解到,有时间你的操作可能并不像预期一样,受 float 类型算法实现,float 精度往往并没有想象中那么高, 如果连续对一个数加一个指定值,可能最后你会得到一个固定的值,它永远不会增加,例如下面的程序:

var x float64
for delta := float64(1); delta+delta > delta; delta += delta {
	x = delta
	if x+1 == x {
		fmt.Printf("%.64f\n", x)
	}
}

输出的结果有点令人意外, x+1以后居然不会有任何变化,而且这样值有非常多, 根据不同初始值,和增加不同大小的数据,出现这种情况的数值也不同。

以下是一部分输出:

9007199254740992.0000000000000000000000000000000000000000000000000000000000000000
18014398509481984.0000000000000000000000000000000000000000000000000000000000000000
36028797018963968.0000000000000000000000000000000000000000000000000000000000000000
72057594037927936.0000000000000000000000000000000000000000000000000000000000000000
144115188075855872.0000000000000000000000000000000000000000000000000000000000000000
288230376151711744.0000000000000000000000000000000000000000000000000000000000000000
576460752303423488.0000000000000000000000000000000000000000000000000000000000000000
1152921504606846976.0000000000000000000000000000000000000000000000000000000000000000
2305843009213693952.0000000000000000000000000000000000000000000000000000000000000000
4611686018427387904.0000000000000000000000000000000000000000000000000000000000000000
9223372036854775808.0000000000000000000000000000000000000000000000000000000000000000
..........

如果你的程序向下面这样一直增加一个固定值,也许会像这样,数值到一个固定值后再也不会发生任何变化。

var x, last float64
for x = 9007199254740992; x < math.MaxFloat64; x++ {
	if x == last {
		fmt.Printf("%.64f\n", x)
	}

	last = x
}

但是我们也不用太过的担心,往常这些数值都非常大,至少我很少处理这么大的 float 数值。 我想你应该了解到这个问题,往往出现 float 操作无效的问题可能并不是这个包导致的,而是 float 精度的问题导致的。

Index

Package Files

doc.go float32.go float64.go

func AddFloat32 Uses

func AddFloat32(addr *float32, delta float32) (new float32)

AddFloat32 atomically adds delta to *addr and returns the new value.

func AddFloat64 Uses

func AddFloat64(addr *float64, delta float64) (new float64)

AddFloat64 atomically adds delta to *addr and returns the new value.

func CompareAndSwapFloat32 Uses

func CompareAndSwapFloat32(addr *float32, old, new float32) (swapped bool)

CompareAndSwapFloat32 executes the compare-and-swap operation for an float32 value.

func CompareAndSwapFloat64 Uses

func CompareAndSwapFloat64(addr *float64, old, new float64) (swapped bool)

CompareAndSwapFloat64 executes the compare-and-swap operation for an float64 value.

func LoadFloat32 Uses

func LoadFloat32(addr *float32) (val float32)

LoadFloat32 atomically loads *addr.

func LoadFloat64 Uses

func LoadFloat64(addr *float64) (val float64)

LoadFloat64 atomically loads *addr.

func StoreFloat32 Uses

func StoreFloat32(addr *float32, val float32)

StoreFloat32 atomically stores val into *addr.

func StoreFloat64 Uses

func StoreFloat64(addr *float64, val float64)

StoreFloat64 atomically stores val into *addr.

func SwapFloat32 Uses

func SwapFloat32(addr *float32, new float32) (old float32)

SwapFloat32 atomically stores new into *addr and returns the previous *addr value.

func SwapFloat64 Uses

func SwapFloat64(addr *float64, new float64) (old float64)

SwapFloat64 atomically stores new into *addr and returns the previous *addr value.

Package exatomic imports 2 packages (graph). Updated 2018-12-23. Refresh now. Tools for package owners.