Go中数字(字符串类型)的高效反向索引

T.B*_*.BJ 2 string integer go

背景

TLDR(和简化版):给定一个 string s,其中s是任何正整数,反转顺序并对每个数字乘以其新索引 (+1) 求和。

例如,从“98765”返回的值将是:(1x5) + (2x6) + (3x7) + (4x8) + (5*9)= 115

我当前的工作解决方案可以在这里找到:Go Playground。我想知道是否有更好的方法来做到这一点,无论是可读性还是效率。例如,我决定使用count变量而不是使用iand ,len因为它看起来更清晰。我也不太熟悉int/string转换,但我假设strconv需要使用。

func reverseStringSum(s string) int {
    total := 0
    count := 1
    for i := len(s) - 1; i >= 0; i-- {
        char := string([]rune(s)[i])
        num, _ := strconv.Atoi(char)
        total += count * num
        count++
    }
    return total
}
Run Code Online (Sandbox Code Playgroud)

roc*_*a2q 5

这是解决整个问题的有效方法:sum("987-65") = 115。完整的问题记录在您的工作解决方案链接中:https ://go.dev/play/p/DJ1ZYYDFnfq 。

\n
package main\n\nimport "fmt"\n\nfunc reverseSum(s string) int {\n    sum := 0\n    for i, j := len(s)-1, 0; i >= 0; i-- {\n        d := int(s[i]) - \'0\'\n        if 0 <= d && d <= 9 {\n            j++\n            sum += j * d\n        }\n    }\n    return sum\n}\n\nfunc main() {\n    s := "987-65"\n    sum := reverseSum(s)\n    fmt.Println(sum)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

https://go.dev/play/p/bx7wfmtXaie

\n
115\n
Run Code Online (Sandbox Code Playgroud)\n
\n

由于我们谈论的是高效的 Go 代码,因此我们需要一些 Go 基准测试。

\n
$ go test reversesum_test.go -bench=. -benchmem\n\nBenchmarkSumTBJ-8     4001182   295.8 ns/op     52 B/op   6 allocs/op\nBenchmarkSumA2Q-8   225781720     5.284 ns/op    0 B/op   0 allocs/op\n
Run Code Online (Sandbox Code Playgroud)\n

您的解决方案(TBJ)很慢。

\n

reversesum_test.go:

\n
package main\n\nimport (\n    "strconv"\n    "strings"\n    "testing"\n)\n\nfunc reverseSumTBJ(s string) int {\n    total := 0\n    count := 1\n    for i := len(s) - 1; i >= 0; i-- {\n        char := string([]rune(s)[i])\n        num, _ := strconv.Atoi(char)\n        total += count * num\n        count++\n    }\n    return total\n}\n\nfunc BenchmarkSumTBJ(b *testing.B) {\n    for n := 0; n < b.N; n++ {\n        rawString := "987-65"\n        stringSlice := strings.Split(rawString, "-")\n        numberString := stringSlice[0] + stringSlice[1]\n        reverseSumTBJ(numberString)\n    }\n}\n\nfunc reverseSumA2Q(s string) int {\n    sum := 0\n    for i, j := len(s)-1, 0; i >= 0; i-- {\n        d := int(s[i]) - \'0\'\n        if 0 <= d && d <= 9 {\n            j++\n            sum += j * d\n        }\n    }\n    return sum\n}\n\nfunc BenchmarkSumA2Q(b *testing.B) {\n    for n := 0; n < b.N; n++ {\n        rawString := "987-65"\n        reverseSumA2Q(rawString)\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n

逆总和是计算CAS 登记号校验位这一更大问题的一部分。

\n
package main\n\nimport "fmt"\n\n// CASRNCheckDigit returns the computed\n// CAS Registry Number check digit.\nfunc CASRNCheckDigit(s string) string {\n    // CAS Registry Number\n    // https://en.wikipedia.org/wiki/CAS_Registry_Number\n    //\n    // The check digit is found by taking the last digit times 1,\n    // the preceding digit times 2, the preceding digit times 3 etc.,\n    // adding all these up and computing the sum modulo 10.\n    //\n    // The CAS number of water is 7732-18-5:\n    // the checksum 5 is calculated as\n    // (8\xc3\x971 + 1\xc3\x972 + 2\xc3\x973 + 3\xc3\x974 + 7\xc3\x975 + 7\xc3\x976)\n    // = 105; 105 mod 10 = 5.\n    //\n    // Check Digit Verification of CAS Registry Numbers\n    // https://www.cas.org/support/documentation/chemical-substances/checkdig\n\n    for i, sep := 0, 0; i < len(s); i++ {\n        if s[i] == \'-\' {\n            sep++\n            if sep == 2 {\n                s = s[:i]\n                break\n            }\n        }\n    }\n\n    sum := 0\n    for i, j := len(s)-1, 0; i >= 0; i-- {\n        d := int(s[i]) - \'0\'\n        if 0 <= d && d <= 9 {\n            j++\n            sum += j * d\n        }\n    }\n    return string(rune(sum%10 + \'0\'))\n}\n\nfunc main() {\n    var rn, cd string\n    // 987-65-5: Adenosine 5\'-triphosphate disodium salt\n    // https://www.chemicalbook.com/CASEN_987-65-5.htm\n    rn = "987-65"\n    cd = CASRNCheckDigit(rn)\n    fmt.Println("CD:", cd, "\\tRN:", rn)\n    // 732-18-5: Water\n    // https://www.chemicalbook.com/CASEN_7732-18-5.htm\n    rn = "7732-18-5"\n    cd = CASRNCheckDigit(rn)\n    fmt.Println("CD:", cd, "\\tRN:", rn)\n    // 7440-21-3: Silicon\n    // https://www.chemicalbook.com/CASEN_7440-21-3.htm\n    rn = "7440-21-3"\n    cd = CASRNCheckDigit(rn)\n    fmt.Println("CD:", cd, "\\tRN:", rn)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

https://go.dev/play/p/VYh-5LuGpCn

\n
BenchmarkCD-4   37187641   30.29 ns/op   4 B/op   1 allocs/op\n
Run Code Online (Sandbox Code Playgroud)\n