乘除程序问题
在据卡特兰数公式, 解决 leetcode-96 不同的二叉搜寻树时, 遇到一个 十分诡异 的问题,
package main
import "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 main
import "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 2
2 * (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 main
import "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 main
import "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 main
import "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 多平台公布