math: allow i64 in digits function and add count_digits function (#13729)

pull/13735/head
kylepritchard 2022-03-14 08:41:01 +00:00 committed by GitHub
parent c8b0f51c13
commit a8f6574471
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 106 additions and 16 deletions

View File

@ -42,23 +42,69 @@ pub fn degrees(radians f64) f64 {
return radians * (180.0 / pi) return radians * (180.0 / pi)
} }
// digits returns an array of the digits of n in the given base. [params]
pub fn digits(_n int, base int) []int { pub struct DigitParams {
if base < 2 { base int = 10
panic('digits: Cannot find digits of n with base $base') reverse bool
}
// digits returns an array of the digits of `num` in the given optional `base`.
// The `num` argument accepts any integer type (i8|i16|int|isize|i64), and will be cast to i64
// The `base:` argument is optional, it will default to base: 10.
// This function returns an array of the digits in reverse order i.e.:
// Example: assert math.digits(12345, base: 10) == [5,4,3,2,1]
// You can also use it, with an explicit `reverse: true` parameter,
// (it will do a reverse of the result array internally => slower):
// Example: assert math.digits(12345, reverse: true) == [1,2,3,4,5]
pub fn digits(num i64, params DigitParams) []int {
// set base to 10 initially and change only if base is explicitly set.
mut b := params.base
if b < 2 {
panic('digits: Cannot find digits of n with base $b')
} }
mut n := _n mut n := num
mut sign := 1 mut sign := 1
if n < 0 { if n < 0 {
sign = -1 sign = -1
n = -n n = -n
} }
mut res := []int{} mut res := []int{}
for n != 0 { if n == 0 {
res << (n % base) * sign // short-circuit and return 0
n /= base res << 0
}
return res return res
}
for n != 0 {
next_n := n / b
res << int(n - next_n * b)
n = next_n
}
if sign == -1 {
res[res.len - 1] *= sign
}
if params.reverse {
res = res.reverse()
}
return res
}
// count_digits return the number of digits in the number passed.
// Number argument accepts any integer type (i8|i16|int|isize|i64) and will be cast to i64
pub fn count_digits(number i64) int {
mut n := number
if n == 0 {
return 1
}
mut c := 0
for n != 0 {
n = n / 10
c++
}
return c
} }
// minmax returns the minimum and maximum value of the two provided. // minmax returns the minimum and maximum value of the two provided.

View File

@ -914,14 +914,40 @@ fn test_lcm() {
} }
fn test_digits() { fn test_digits() {
digits_in_10th_base := digits(125, 10) // a small sanity check with a known number like 100,
assert digits_in_10th_base[0] == 5 // just written in different base systems:
assert digits_in_10th_base[1] == 2 assert digits(100, reverse: true) == [1, 0, 0]
assert digits_in_10th_base[2] == 1 assert digits(100, base: 2, reverse: true) == [1, 1, 0, 0, 1, 0, 0]
digits_in_16th_base := digits(15, 16) assert digits(100, base: 3, reverse: true) == [1, 0, 2, 0, 1]
assert digits_in_16th_base[0] == 15 assert digits(100, base: 4, reverse: true) == [1, 2, 1, 0]
negative_digits := digits(-4, 2) assert digits(100, base: 8, reverse: true) == [1, 4, 4]
assert negative_digits[2] == -1 assert digits(100, base: 10, reverse: true) == [1, 0, 0]
assert digits(100, base: 12, reverse: true) == [8, 4]
assert digits(100, base: 16, reverse: true) == [6, 4]
assert digits(100, base: 20, reverse: true) == [5, 0]
assert digits(100, base: 32, reverse: true) == [3, 4]
assert digits(100, base: 64, reverse: true) == [1, 36]
assert digits(100, base: 128, reverse: true) == [100]
assert digits(100, base: 256, reverse: true) == [100]
assert digits(1234432112344321) == digits(1234432112344321, reverse: true)
assert digits(1234432112344321) == [1, 2, 3, 4, 4, 3, 2, 1, 1, 2, 3, 4, 4, 3, 2, 1]
assert digits(125, base: 10, reverse: true) == [1, 2, 5]
assert digits(125, base: 10).reverse() == [1, 2, 5]
assert digits(15, base: 16, reverse: true) == [15]
assert digits(127, base: 16, reverse: true) == [7, 15]
assert digits(65535, base: 16, reverse: true) == [15, 15, 15, 15]
assert digits(-65535, base: 16, reverse: true) == [-15, 15, 15, 15]
assert digits(-127) == [7, 2, -1]
assert digits(-127).reverse() == [-1, 2, 7]
assert digits(-127, reverse: true) == [-1, 2, 7]
assert digits(234, base: 7).reverse() == [4, 5, 3]
assert digits(67432, base: 12).reverse() == [3, 3, 0, 3, 4]
} }
// Check that math functions of high angle values // Check that math functions of high angle values
@ -966,3 +992,21 @@ fn test_powi() {
assert powi(0, -2) == -1 // div by 0 assert powi(0, -2) == -1 // div by 0
assert powi(2, -1) == 0 assert powi(2, -1) == 0
} }
fn test_count_digits() {
assert count_digits(-999) == 3
assert count_digits(-100) == 3
assert count_digits(-99) == 2
assert count_digits(-10) == 2
assert count_digits(-1) == 1
assert count_digits(0) == 1
assert count_digits(1) == 1
assert count_digits(10) == 2
assert count_digits(99) == 2
assert count_digits(100) == 3
assert count_digits(999) == 3
//
assert count_digits(12345) == 5
assert count_digits(123456789012345) == 15
assert count_digits(-67345) == 5
}