去 atomic.AddFloat32()

标签 go floating-point add atomic

我需要一个函数来在 Go 中自动添加 float32 值。 这是基于我发现的一些 C 代码得出的:

package atomic

import (
    "sync/atomic"
    "unsafe"
    "math"
)

func AddFloat32(addr *float32, delta float32) (new float32) {
    unsafeAddr := (*uint32)(unsafe.Pointer(addr))

    for {
        oldValue := math.Float32bits(*addr)
        new       = *addr + delta
        newValue := math.Float32bits(new)

        if atomic.CompareAndSwapUint32(unsafeAddr, oldValue, newValue) {
            return
        }
    }
}

它应该工作吗(即真的是原子的)?在 Go 中有更好/更快的方法吗?

最佳答案

从Go标准库中寻找一些代码进行适配。例如,来自 go/src/sync/atomic/64bit_arm.go

func addUint64(val *uint64, delta uint64) (new uint64) {
    for {
        old := *val
        new = old + delta
        if CompareAndSwapUint64(val, old, new) {
            break
        }
    }
    return
}

对于 float32 来说,

package main

import (
    "fmt"
    "math"
    "sync/atomic"
    "unsafe"
)

func AddFloat32(val *float32, delta float32) (new float32) {
    for {
        old := *val
        new = old + delta
        if atomic.CompareAndSwapUint32(
            (*uint32)(unsafe.Pointer(val)),
            math.Float32bits(old),
            math.Float32bits(new),
        ) {
            break
        }
    }
    return
}

func main() {
    val, delta := float32(math.Pi), float32(math.E)
    fmt.Println(val, delta, val+delta)
    new := AddFloat32(&val, delta)
    fmt.Println(val, new)
}

输出:

3.1415927 2.7182817 5.8598747
5.8598747 5.8598747

关于去 atomic.AddFloat32(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27492349/

相关文章:

mysql - Symfony 更新实体值 + 1

java - parseFloat() 与 parseDouble()

javascript - -= 0.1 奇怪的结果

java - Float.MIN_VALUE 和 Float.MIN_NORMAL 之间的区别?

c - C 和汇编语言中局部变量和静态变量的加法是如何工作的

java - 如何以编程方式正确添加 View ?

curl - 使用 Golang 的 net/http header

go - 在一个函数中创建结构以在另一个函数中使用

csv - Go stdlib 是否具有将 csv 文件读入 []map[string]string 的功能?

go - 有人可以解释一下 "Readdir"和 "Open"包装方法吗