还有另一种测试big.Int是否为0的方法吗?

问题描述

我正在使用big.Int,需要测试0。现在,我正在使用zero = big.NewInt(0)Cmp(zero)==0,它们工作正常,但是我想知道是否存在专用于0的更快方法(我需要这个程序要非常快)?

解决方法

big.Int公开Int.Bits()来访问表示形式的原始字节,它是一个切片,并且共享相同的基础数组:不复制返回的切片。这样很快。 “缺少底层Int功能的支持实现”

完美,正是我们想要的。

0。测试0

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

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

还请注意,有一个Int.BitLen()函数返回此函数,该函数还指出“ 0的位长度为0” 。所以我们也可以使用这个:

if i1.BitLen() == 0 {
}

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

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进行比较比使用{{1}与代表big.Int的另一个0进行比较要快 20倍 }的速度还快10倍

1。测试Int.BitLen()

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

此绝对值属性很重要,因为0返回绝对值。因此,在非零值检查的情况下,仅位片是不够的,因为它不携带任何符号信息。

因此可以通过检查位内容是否表示Int.Bits()以及符号是否为正来对1进行测试:

1

让我们对此进行基准测试,并将数字与func isOne(i *big.Int) bool { bits := i.Bits() return len(bits) == 1 && bits[0] == 1 && i.Sign() > 0 } 进行比较:

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) {
        }
    }
}

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