一不留神就掉坑

简介: 一不留神就掉坑

乘除顺序问题


在据卡特兰数公式,解决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问题

微信截图_20230925213548.png

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

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

微信截图_20230925213557.png

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

微信截图_20230925214129.png

目录
相关文章
|
3月前
|
存储 缓存 JSON
一行代码,我优化掉了1G内存占用
这里一行代码,指的是:String.intern()的调用,为了调用这一行代码,也写了几十行额外的代码。
|
3月前
|
JavaScript 前端开发 开发者
使用 clearError 清除已处理的错误
【8月更文挑战第9天】在编程中,使用`clearError`方法清除已处理的错误能避免错误累积导致程序行为异常或性能下降。此操作还能提升代码的可读性和可维护性,确保程序逻辑的正确性。具体应用时,需确定错误处理位置并在确认错误妥善处理后调用`clearError`。例如,在JavaScript中,可在`catch`块处理完错误后调用该方法。需要注意的是,应谨慎使用此方法以避免掩盖潜在问题,并应在清除前记录错误信息以便后续调试。
|
6月前
|
Arthas 存储 Java
不重启 JVM,如何替换掉已经加载的类
不重启 JVM,如何替换掉已经加载的类
74 0
HOperatorSet.GenRandomRegions 有内存泄漏或缓存,释放不掉
HOperatorSet.GenRandomRegions 有内存泄漏或缓存,释放不掉
一个UE频繁掉网的问题
这个UE频繁掉网的问题,其实蛮low的,熟悉的人,看一个参数值就搞定这个问题了,但是还是做个记录。问题背景是运营商指定UE锁在某个NR小区,在一个区域的弱信号点(RSRP -110dbm左右)进行TPUT测试,但是最后发现UE在-106 dbm左右时就会掉网,没办法进行测试。测试反馈:UE锁在NR N41 520110/344小区上,一开始可以正常进行TPUT,随着往弱信号的方向上移动,UE就会出现掉网。
|
Android开发 容器
要小心点,不要掉 Recomposition 带来的性能坑了
今天我们就来聊聊可能因为没理解透 Recomposition 而写出的性能问题。
100 0
|
设计模式 算法 Java
干掉 “重复代码” 的技巧有哪些
软件工程师和码农最大的区别就是平时写代码时习惯问题,码农很喜欢写重复代码而软件工程师会利用各种技巧去干掉重复的冗余代码。
133 0
干掉 “重复代码” 的技巧有哪些
8080端口莫名被占用 ,如何结束掉进程
8080端口莫名被占用 ,如何结束掉进程
247 0
|
缓存 Java 数据库
如何避免无意间创建多余对象
6 避免创建不必要的对象 从字面意思上来看,大家肯定都知道创建不必要的对象是错误的做法。但这一节其实主要是提醒我们避免无意识的创建不必要对象的代码写法。
如何避免无意间创建多余对象