乘除程序问题


在据卡特兰数公式,解决leetcode-96 不同的二叉搜寻树时,遇到一个十分诡异的问题,

package mainimport "fmt"func main() {    for i := 0; i <= 40; i++ {        fmt.Printf("第%d个卡特兰数为:%d\n", i, numTrees(i))    }}func numTrees(n int) int {    rs := 1    for i := 0; i < n; i++ {        rs = rs * 2 * (2*i + 1) / (i + 2)        //rs *= 2 * (2*i + 1) / (i + 2)    }    return rs}


即 正文掉的这一行,竟然和上一行得出了齐全不同的后果. 尽管马上解决,但对固有认知影响微小---难道对始终以来司空见惯的乘法语法糖了解有误???


*= 为乘法和赋值运算符,它将右操作数与左操作数相乘,并将后果赋给左操作数. C *= A 相当于 C = C * A

读了一遍感觉没问题,那起因出在哪里呢?


构建demo,

package mainimport "fmt"func main() {    rs1 := 2    rs2 := 2    i := 3    fmt.Println("以后的rs1,rs2为:", rs1, rs2)    fmt.Println("2 * (2*i + 1) / (i + 2)为:", 2*(2*i+1)/(i+2))    rs1 = rs1 * 2 * (2*i + 1) / (i + 2)    rs2 *= 2 * (2*i + 1) / (i + 2)    fmt.Println("最初rs1 is,rs2 is:", rs1, rs2)}


后果为

以后的rs1,rs2为: 2 22 * (2*i + 1) / (i + 2)为: 2最初rs1 is,rs2 is: 5 4


初步判断,问题出在除法这里. 去掉除法局部后,的确失去的后果都一样.


在数学中 乘除运算不分先后. 但因为可能无奈整除,对计算机来说,除不尽的局部会一律向下取整。所以乘除的先后顺序,理论是对最终后果有影响的

对于 rs1,其等于 2 * 2 * 7 / 5,即28/5,向下取整,即为5

对于rs2, 会先计算前面局部2 * (2*3 + 1) / (3 + 2) = 14/5 = 2, 而后计算 2*2 = 4




crontab配置问题


Linux自带的crontab只能准确到分钟,而某些语言的工具包,能够提供准确到秒的crontab.

但在应用时,务必留神,如0 */10 * * * *,是从下一个 xx:x0:00 开始,每10分钟执行一次.

如写成 * */10 * * * *, 就成了每秒钟执行一次,如有对数据库的读写操作,会造成微小压力.

上线前能够用这个工具, 选Java(Spring)项,来校验一下




map和slice变量的赋值作用范畴问题


package mainimport "fmt"func main() {    m := make(map[string]string)    m["gender"] = "女"    fmt.Println("map is:", m)    f1(&m)    fmt.Println("map is:", m)}func f1(m1 *map[string]string) *map[string]string {    (*m1)["name"] = "dashen"    (*m1)["gender"] = "男"    return m1}


运行后果:

map is: map[gender:女]map is: map[gender:男 name:dashen]


但这种写法,十分不Golang!

在函数A中定义一个map记为m,想要在函数B,函数C中对其进行赋值或批改,是没有必要传指针的

package mainimport "fmt"func main() {    m := make(map[string]string)    m["gender"] = "女"    fmt.Println("map is:", m)    f1(m)    fmt.Println("map is:", m)}func f1(m1 map[string]string) map[string]string {    m1["name"] = "dashen"    m1["gender"] = "男"    return m1}


运行后果:

map is: map[gender:女]map is: map[gender:男 name:dashen]


对于slice,状况有所不同

package mainimport "fmt"func main() {    sli := make([]string, 1)    sli[0] = "宋江"    fmt.Println("slice is:", sli)    f1(sli)    fmt.Println("slice is:", sli)}func f1(sli1 []string) []string {    sli1[0] = "晁盖"    return sli1}

运行后果:

slice is: [宋江]slice is: [晁盖]


与map的"全副援用"不同,slice只是底层数组是指针类型,长度和容量不是.

对于下面这样只批改原有值,而没有append操作的行为,是没有问题的.

但如果有append操作,引发了扩容,底层数组的地址变了,则将会得不到预期后果




sql的update问题


update一条不存在的记录,Affected rows为0,但并不会报错

UPDATE a SET name="卡拉马佐夫兄弟" WHERE id=12345


update一条存在的记录,但理论并没有对现有内容进行更新,Affected rows也会是0




Golang 58个坑

本文由mdnice多平台公布