Skip to content

Commit

Permalink
feat: huge 包 NewInt 函数支持 string、bool、float 类型
Browse files Browse the repository at this point in the history
  • Loading branch information
kercylan98 committed Jan 18, 2024
1 parent 9dba7ff commit c4605cc
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 12 deletions.
67 changes: 55 additions & 12 deletions utils/huge/int.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,70 @@ var (

type Int big.Int

// NewInt 创建一个 Int
func NewInt[T generic.Number](x T) *Int {
return (*Int)(big.NewInt(int64(x)))
}

// NewIntByString 通过字符串创建一个 Int
// - 如果字符串不是一个合法的数字,则返回 0
func NewIntByString(i string) *Int {
v, suc := new(big.Int).SetString(i, 10)
if !suc {
return IntZero.Copy()
// NewInt 创建一个 Int 对象,该对象的值为 x
func NewInt[T generic.Basic](x T) *Int {
var xa any = x
switch x := xa.(type) {
case int:
return (*Int)(big.NewInt(int64(x)))
case int8:
return (*Int)(big.NewInt(int64(x)))
case int16:
return (*Int)(big.NewInt(int64(x)))
case int32:
return (*Int)(big.NewInt(int64(x)))
case int64:
return (*Int)(big.NewInt(x))
case uint:
return (*Int)(big.NewInt(int64(x)))
case uint8:
return (*Int)(big.NewInt(int64(x)))
case uint16:
return (*Int)(big.NewInt(int64(x)))
case uint32:
return (*Int)(big.NewInt(int64(x)))
case uint64:
return (*Int)(big.NewInt(int64(x)))
case string:
si, suc := new(big.Int).SetString(x, 10)
if !suc {
return (*Int)(big.NewInt(0))
}
return (*Int)(si)
case bool:
if x {
return (*Int)(big.NewInt(1))
}
return (*Int)(big.NewInt(0))
case float32:
return (*Int)(big.NewInt(int64(x)))
case float64:
return (*Int)(big.NewInt(int64(x)))
}
return (*Int)(v)
return (*Int)(big.NewInt(0))
}

// applyIntOperation 应用一个 Int 操作
func applyIntOperation[T generic.Number](v *Int, i T, op func(*big.Int, *big.Int) *big.Int) *Int {
return (*Int)(op(v.ToBigint(), NewInt(i).ToBigint()))
}

// Copy 拷贝当前 Int 对象
func (slf *Int) Copy() *Int {
return (*Int)(new(big.Int).Set(slf.ToBigint()))
}

// Set 设置当前 Int 对象的值为 i
func (slf *Int) Set(i *Int) *Int {
return (*Int)(slf.ToBigint().Set(i.ToBigint()))
}

// SetString 设置当前 Int 对象的值为 i
func (slf *Int) SetString(i string) *Int {
return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i))))
}

// SetInt 设置当前 Int 对象的值为 i
func (slf *Int) SetInt(i int) *Int {
return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i))))
}
Expand Down Expand Up @@ -92,6 +129,9 @@ func (slf *Int) IsZero() bool {
}

func (slf *Int) ToBigint() *big.Int {
if slf == nil {
return big.NewInt(0)
}
return (*big.Int)(slf)
}

Expand Down Expand Up @@ -130,6 +170,9 @@ func (slf *Int) Int64() int64 {
}

func (slf *Int) String() string {
if slf == nil {
return "0"
}
return slf.ToBigint().String()
}

Expand Down
69 changes: 69 additions & 0 deletions utils/huge/int_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package huge_test

import (
"github.com/kercylan98/minotaur/utils/huge"
"testing"
)

func TestNewInt(t *testing.T) {
var cases = []struct {
name string
nil bool
in int64
mul int64
want string
}{
{name: "TestNewIntNegative", in: -1, want: "-1"},
{name: "TestNewIntZero", in: 0, want: "0"},
{name: "TestNewIntPositive", in: 1, want: "1"},
{name: "TestNewIntMax", in: 9223372036854775807, want: "9223372036854775807"},
{name: "TestNewIntMin", in: -9223372036854775808, want: "-9223372036854775808"},
{name: "TestNewIntMulNegative", in: -9223372036854775808, mul: 10000000, want: "-92233720368547758080000000"},
{name: "TestNewIntMulPositive", in: 9223372036854775807, mul: 10000000, want: "92233720368547758070000000"},
{name: "TestNewIntNil", nil: true, want: "0"},
{name: "TestNewIntNilMul", nil: true, mul: 10000000, want: "0"},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
var got *huge.Int
switch {
case c.nil:
if c.mul > 0 {
got = huge.NewInt(0).MulInt64(c.mul)
}
case c.mul == 0:
got = huge.NewInt(c.in)
default:
got = huge.NewInt(c.in).MulInt64(c.mul)
}
if s := got.String(); s != c.want {
t.Errorf("want: %s, got: %s", c.want, got.String())
} else {
t.Log(s)
}
})
}

// other
t.Run("TestNewIntFromString", func(t *testing.T) {
if got := huge.NewInt("1234567890123456789012345678901234567890"); got.String() != "1234567890123456789012345678901234567890" {
t.Fatalf("want: %s, got: %s", "1234567890123456789012345678901234567890", got.String())
}
})
t.Run("TestNewIntFromInt", func(t *testing.T) {
if got := huge.NewInt(1234567890); got.String() != "1234567890" {
t.Fatalf("want: %s, got: %s", "1234567890", got.String())
}
})
t.Run("TestNewIntFromBool", func(t *testing.T) {
if got := huge.NewInt(true); got.String() != "1" {
t.Fatalf("want: %s, got: %s", "1", got.String())
}
})
t.Run("TestNewIntFromFloat", func(t *testing.T) {
if got := huge.NewInt(1234567890.1234567890); got.String() != "1234567890" {
t.Fatalf("want: %s, got: %s", "1234567890", got.String())
}
})
}

0 comments on commit c4605cc

Please sign in to comment.