如果 big.Int 为 0,还有另一种测试方法吗? [英] Is there another way of testing if a big.Int is 0?

查看:135
本文介绍了如果 big.Int 为 0,还有另一种测试方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 big.Int 并且需要测试 0.现在,我正在使用 zero = big.NewInt(0)Cmp(zero)==0 工作正常,但我想知道是否有专门针对 0 的更快方法(我需要这个程序非常快)?

I'm working with big.Ints and need to test for 0. Right now, I'm using zero = big.NewInt(0)and Cmp(zero)==0 which works fine, but I was wondering if there's a quicker way specifically for 0 (I need this program to be very fast)?

推荐答案

big.Int 暴露 Int.Bits() 访问表示的原始字节,它是一个切片,它共享相同的底层数组:不复制返回的切片.所以它很快.它暴露于支持实现缺少的低级 Int 功能".

完美,正是我们想要的.

Perfect, exactly what we want.

big.Int 的文档还指出Int 的零值表示值 0".因此,在零值(代表 0)中,切片将为空(切片的零值是 nilnil 切片的长度是 0).我们可以简单地检查一下:

Documentation of big.Int also states that "the zero value for an Int represents the value 0". So in the zero value (which represents 0) the slice will be empty (zero value for slices is nil and the length of a nil slice is 0). We can simply check that:

if len(i1.Bits()) == 0 {
}

另请注意,有一个 Int.BitLen() 函数返回此值,这也说明0 的位长为 0".所以我们也可以这样使用:

Also note that there is an Int.BitLen() function returning this, which also states that "the bit length of 0 is 0". So we may also use this:

if i1.BitLen() == 0 {
}

让我们对这些解决方案进行基准测试:

Let's benchmark these solutions:

func BenchmarkCompare(b *testing.B) {
    zero := big.NewInt(0)
    i1 := big.NewInt(1)
    i2 := big.NewInt(0)
    for i := 0; i < b.N; i++ {
        if i1.Cmp(zero) == 0 {
        }
        if i2.Cmp(zero) == 0 {
        }
    }
}

func BenchmarkBits(b *testing.B) {
    i1 := big.NewInt(1)
    i2 := big.NewInt(0)
    for i := 0; i < b.N; i++ {
        if len(i1.Bits()) == 0 {
        }
        if len(i2.Bits()) == 0 {
        }
    }
}

func BenchmarkBitLen(b *testing.B) {
    i1 := big.NewInt(1)
    i2 := big.NewInt(0)
    for i := 0; i < b.N; i++ {
        if i1.BitLen() == 0 {
        }
        if i2.BitLen() == 0 {
        }
    }
}

基准测试结果:

BenchmarkCompare-8      76975251            13.3 ns/op
BenchmarkBits-8         1000000000           0.656 ns/op
BenchmarkBitLen-8       1000000000           1.11 ns/op

获取位并将切片长度与 0 进行比较比将其与另一个表示 big.Int 进行比较快 20 倍0,使用 Int.BitLen()快 10 倍.

Getting the bits and comparing the slice length to 0 is 20 times faster than comparing it to another big.Int representing 0, using Int.BitLen() is also 10 times faster.

可以使用类似的方法来测试 big.Int 值是否等于 1,但可能不如测试零快:0 是最特殊的值.它的内部表示是一个 nil 切片,任何其他值都需要一个非 nil 切片.另外:0 还有一个特殊的属性:它的绝对值是它自己.

Something similar could be made to test if a big.Int value equals to 1, but probably not as fast as testing for zero: 0 is the most special value. Its internal representation is a nil slice, any other value requires a non-nil slice. Also: 0 has another special property: its absolute value is itself.

这个绝对值属性很重要,因为Int.Bits() 返回绝对值.因此,在非零值检查的情况下,仅检查位片是不够的,因为它不携带符号信息.

This absolute value property is important, because Int.Bits() returns the absolute value. So in case of a non-zero value checking just the bits slice is insufficient, as it carries no sign information.

所以对1的测试可以通过检查bits内容是否代表1,并且符号为正来实现:

So testing for 1 can be implemented by checking if the bits content represents 1, and the sign is positive:

func isOne(i *big.Int) bool {
    bits := i.Bits()
    return len(bits) == 1 && bits[0] == 1 && i.Sign() > 0
}

让我们对此进行基准测试,并将数字与 one := big.NewInt(1) 进行比较:

Let's benchmark this along with comparing the number to one := big.NewInt(1):

func BenchmarkCompareOne(b *testing.B) {
    one := big.NewInt(1)
    i1 := big.NewInt(0)
    i2 := big.NewInt(1)
    i3 := big.NewInt(2)
    for i := 0; i < b.N; i++ {
        if i1.Cmp(one) == 0 {
        }
        if i2.Cmp(one) == 0 {
        }
        if i3.Cmp(one) == 0 {
        }
    }
}

func BenchmarkBitsOne(b *testing.B) {
    i1 := big.NewInt(0)
    i2 := big.NewInt(1)
    i3 := big.NewInt(2)
    for i := 0; i < b.N; i++ {
        if isOne(i1) {
        }
        if isOne(i2) {
        }
        if isOne(i3) {
        }
    }
}

以及基准测试结果:

BenchmarkCompareOne-8       58631458            18.9 ns/op
BenchmarkBitsOne-8          715606629            1.76 ns/op

还不错!我们测试 1 的方式再次快了 10 倍.

Not bad! Our way of testing for 1 is again 10 times faster.

这篇关于如果 big.Int 为 0,还有另一种测试方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆