diff options
| author | Adrien Hopkins <adrien.p.hopkins@gmail.com> | 2023-09-13 19:38:39 -0500 |
|---|---|---|
| committer | Adrien Hopkins <adrien.p.hopkins@gmail.com> | 2023-09-13 19:38:39 -0500 |
| commit | f657d4257e6b39a3899a2ebef8f30f99ebfb313f (patch) | |
| tree | 16c117ba1ce8c10fd95230fb372c439c1ec6c613 /factors | |
| parent | 345f6bae7b005cdd386833aa496aa71ca11c7b97 (diff) | |
factors: Remove most panics
Panics are not the best way of handling errors in Go. I've replaced
panics with default values whenever a sensible one exists.
Factors(0) does not have a sensible default value (as every number is a
factor of zero), so it still panics.
Diffstat (limited to 'factors')
| -rw-r--r-- | factors/digit_map.go | 20 | ||||
| -rw-r--r-- | factors/factors_test.go | 30 | ||||
| -rw-r--r-- | factors/score.go | 12 |
3 files changed, 46 insertions, 16 deletions
diff --git a/factors/digit_map.go b/factors/digit_map.go index 83606e9..a16f018 100644 --- a/factors/digit_map.go +++ b/factors/digit_map.go @@ -28,6 +28,7 @@ const ( // - it will not be nice to work with Opaque TotativeType = 0x40 // This number is zero, and doesn't have a true totative type. + // (except in radix zero, where zero is considered a factor) Zero TotativeType = 0x00 ) @@ -98,6 +99,10 @@ func Split(digit, radix uint) (regular, totative uint) { // Calculates the regularity index of a number's regular part func calcRegularity(regular, radix uint) uint8 { + if regular == 0 && radix == 0 { + return 1 + } + regularity, radixPower := uint8(0), uint(1) for radixPower%regular != 0 { regularity++ @@ -125,10 +130,8 @@ func calcTotativeType(totative, radix uint) TotativeType { } // Gets the regularity and totative type of one digit in a radix +// In radix zero, zero is type 1R, one is type 0R, and everything else is 0P. func GetDigitType(digit, radix uint) DigitType { - if radix < 2 { - panic("Radices cannot be less than 2!") - } radixPF := PrimeFactorize(radix) digitPF := PrimeFactorize(digit) regular, totative := splitPF(digitPF, radixPF) @@ -139,13 +142,14 @@ func GetDigitType(digit, radix uint) DigitType { // Gets the regularity and totative type of each digit in a radix func DigitMap(radix uint) []DigitType { - if radix < 2 { - panic("Radices cannot be less than 2!") - } radixPF := PrimeFactorize(radix) types := make([]DigitType, radix, radix) - types[0] = zeroType - types[1] = oneType + if radix > 0 { + types[0] = zeroType + } + if radix > 1 { + types[1] = oneType + } for d := uint(2); d < radix; d++ { digitPF := PrimeFactorize(d) regular, totative := splitPF(digitPF, radixPF) diff --git a/factors/factors_test.go b/factors/factors_test.go index dec651c..a18d30b 100644 --- a/factors/factors_test.go +++ b/factors/factors_test.go @@ -68,10 +68,6 @@ var totativeRatioCases = map[uint]float64{ } func totativeRatio(n uint) float64 { - if n == 0 { - panic("0 has no totative ratio!") - } - return float64(Totient(n)) / float64(n) } @@ -214,6 +210,8 @@ var ( pt = DigitType{0, Opaque} // 0P - opaque totatives ) var digitMapCases = map[uint][]DigitType{ + 0: []DigitType{}, + 1: []DigitType{zt}, 2: []DigitType{zt, ot}, 3: []DigitType{zt, ot, wt}, 4: []DigitType{zt, ot, ft, wt}, @@ -263,14 +261,38 @@ func TestGetDigitType(t *testing.T) { } } +// A few test cases related to radix zero +func TestGetDigitTypeMisc(t *testing.T) { + t.Run("GetDigitType(0, 0)", func(t *testing.T) { + if GetDigitType(0, 0) != ft { + t.Errorf("GetDigitType(0, 0) = %s, expected 1R", GetDigitType(0, 0)) + } + }) + t.Run("GetDigitType(1, 0)", func(t *testing.T) { + if GetDigitType(1, 0) != ot { + t.Errorf("GetDigitType(1, 0) = %s, expected 0R", GetDigitType(1, 0)) + } + }) + t.Run("GetDigitType(2, 0)", func(t *testing.T) { + if GetDigitType(2, 0) != pt { + t.Errorf("GetDigitType(2, 0) = %s, expected 0P", GetDigitType(2, 0)) + } + }) +} + var splitCases = map[uintPair]uintPair{ // digit, radix, regular part, totative part uintPair{0, 0}: uintPair{0, 1}, + uintPair{0, 1}: uintPair{1, 0}, uintPair{0, 2}: uintPair{1, 0}, uintPair{0, 12}: uintPair{1, 0}, uintPair{1, 0}: uintPair{1, 1}, uintPair{20, 0}: uintPair{1, 20}, uintPair{360, 0}: uintPair{1, 360}, + uintPair{1, 1}: uintPair{1, 1}, + uintPair{12, 1}: uintPair{1, 12}, + uintPair{87, 1}: uintPair{1, 87}, + uintPair{120, 1}: uintPair{1, 120}, uintPair{1, 2}: uintPair{1, 1}, uintPair{1, 3}: uintPair{1, 1}, uintPair{1, 7}: uintPair{1, 1}, diff --git a/factors/score.go b/factors/score.go index b47aac4..9288e8f 100644 --- a/factors/score.go +++ b/factors/score.go @@ -1,5 +1,7 @@ package factors +import "math" + // Score returns a "factor score" equal to the sum of the reciprocoals // of the number n's factors. // Rationale: @@ -17,7 +19,7 @@ package factors // a factor's score is the probability a random number is divisible by it. func Score(n uint) float64 { if n == 0 { - panic("Cannot get factor score of 0.") + return math.NaN() } factorSum := uint(0) @@ -27,9 +29,11 @@ func Score(n uint) float64 { return float64(factorSum) / float64(n) } -// BasicRank returns a rank describing how well a base handles the simplest -// fractions (1/2, 1/3, 1/4 and 1/5) -// also known as 2345 Rank +// BasicRank returns a rank describing how well a radix handles the simplest +// fractions (1/2, 1/3, 1/4 and 1/5). Zero and one are not true radices, +// but because this rank otherwise only depends on a radix's remainder +// mod 60, they have the same ranks as 60 and 61 (A+, F~). +// Also known as 2345 Rank. func BasicRank(n uint) string { var firstRank, secondRank string if n%2 == 0 { |
