V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MiketsuSmasher
V2EX  ›  程序员

"0 << 1 + 1"到底是等于 0 还是 1?

  •  
  •   MiketsuSmasher · 2022-01-06 08:23:16 +08:00 · 4562 次点击
    这是一个创建于 1039 天前的主题,其中的信息可能已经有所发展或是发生改变。

    昨天碰上这个问题,着实把我坑惨了,花了一个晚上搞明白,python 和 golang 按位移动运算符的优先级居然不一样

    python:

    print(0 << 1 + 1)
    

    输出:0

    golang:

    import "fmt"
    
    func main() {
        fmt.Println(0 << 1 + 1)
    }
    

    输出:1

    第 1 条附言  ·  2022-01-06 09:00:59 +08:00

    为了让python和golang的行为一致,我只好为表达式里的"0 << 1"加了括号

    37 条回复    2022-01-08 10:13:03 +08:00
    loading
        1
    loading  
       2022-01-06 08:25:19 +08:00
    感谢提醒,但像我这种菜鸟都是一堆括号的,如果有人说括号看晕,他是连工具都不会用的比我更菜的鸟。
    Aruforce
        2
    Aruforce  
       2022-01-06 08:29:01 +08:00 via Android
    感觉 0 好理解一点儿…
    Rocketer
        3
    Rocketer  
       2022-01-06 08:32:34 +08:00 via iPhone
    凡是有歧义的一律加括号
    dejavuwind
        4
    dejavuwind  
       2022-01-06 09:07:43 +08:00
    不加括号的话 Java 的计算结果也是 0
    cccer
        5
    cccer  
       2022-01-06 09:08:51 +08:00
    不同类型的操作符混合肯定是要加括号,就算自己能肯定顺序别人也不一定明白。
    iold
        6
    iold  
       2022-01-06 09:14:48 +08:00
    2i2Re2PLMaDnghL
        7
    2i2Re2PLMaDnghL  
       2022-01-06 09:21:35 +08:00
    Pascal 里面 and 和 or 优先级比数学运算还高(因为同时被视为位运算符
    判断条件就一直一堆括号,习惯了除了日常习惯的(基本就是四则运算)或者倒错就会立刻严重出错(比如 4/2-2 ,或者矩阵运算)的或者符合结合律的运算以外都加括号。
    nekoneko
        8
    nekoneko  
       2022-01-06 09:22:14 +08:00   ❤️ 1
    因为只有 go 的操作符优先级是 移位优先于加减 的
    其他 java python c 都是 加减优先于移位
    iovekkk
        9
    iovekkk  
       2022-01-06 09:24:40 +08:00
    头像不错
    www5070504
        10
    www5070504  
       2022-01-06 09:37:31 +08:00
    我猜一会就有人跳出来说基本功 balabala 的
    Leonard
        11
    Leonard  
       2022-01-06 09:44:31 +08:00
    不用在意这种事,加括号解决完事,大家看着都清晰方便。
    这种一般只有某些考试里会考,真使用时用不上这些知识。
    ychost
        12
    ychost  
       2022-01-06 10:07:55 +08:00
    工作这么多年除了之前写嵌入式用到了位移,现在写 WEB 基本没用过
    rillhu
        13
    rillhu  
       2022-01-06 10:16:00 +08:00
    看具体的语言吧,本人只熟悉 C ,C 里面`+` > `<<`,所以结果上述结果是 0 。
    ipwx
        14
    ipwx  
       2022-01-06 10:23:48 +08:00
    一般除了加减乘除这种运算,一律加括号
    msg7086
        15
    msg7086  
       2022-01-06 10:31:08 +08:00 via Android
    位移运算必加括号,血(不是)的教训。
    mainjzb
        16
    mainjzb  
       2022-01-06 10:31:17 +08:00
    fmt.Println(0<<1 + 1)
    go 会按优先级自动格式化,建议其他语言学习
    yazinnnn
        17
    yazinnnn  
       2022-01-06 10:35:30 +08:00
    我看谁还嘲笑 lisp 括号罗嗦
    socketpeng
        18
    socketpeng  
       2022-01-06 10:39:54 +08:00
    加个括号很难么?别人不知道,要是我在实际生产环境中发现这种代码,直接开骂
    BeyondBouds
        19
    BeyondBouds  
       2022-01-06 10:50:16 +08:00
    i+++++i-----的变种? 这种不直接打残?
    majula
        20
    majula  
       2022-01-06 11:08:35 +08:00 via iPhone
    即使很熟悉运算符优先级,在书写可能有歧义的数学表达式时也尽可能加上括号
    littlewing
        21
    littlewing  
       2022-01-06 11:48:31 +08:00
    没必要纠结这种东西,啥,你说面试有人问?我反手就给他一巴掌
    yangyaofei
        22
    yangyaofei  
       2022-01-06 11:55:28 +08:00
    这种的意义是啥, 就像 ++i+++=++i++, 没有任何意义
    cmdOptionKana
        23
    cmdOptionKana  
       2022-01-06 11:59:58 +08:00
    @yazinnnn “嘲笑 lisp 括号罗嗦”本来就是菜鸟行为
    yazinnnn
        24
    yazinnnn  
       2022-01-06 12:02:14 +08:00
    @cmdOptionKana 本站就不少。
    mikewang
        25
    mikewang  
       2022-01-06 12:03:20 +08:00
    涉及到位运算的,还是都加上括号吧。位运算本身就不是非常优美,多加点括号啰嗦一下也没什么事。
    ch2
        26
    ch2  
       2022-01-06 12:10:17 +08:00
    不同语言运算符优先级不一样,位运算在 C 系里优先级很低的
    acmore
        27
    acmore  
       2022-01-06 13:01:35 +08:00
    遇事不决加括号,编程不仰赖记忆力
    AoEiuV020CN
        28
    AoEiuV020CN  
       2022-01-06 13:12:04 +08:00
    先乘除后加减,其他尽量都上括号,
    crayygy
        29
    crayygy  
       2022-01-06 14:41:35 +08:00
    都说加括号,我不太一样,我宁可多用一个变量然后分两步写,位运算尽量分开,方便 debug
    icenine
        30
    icenine  
       2022-01-06 15:17:49 +08:00
    直接上括号,但凡你会一种以上的语言,深究这种语法细节有啥意义
    cht
        31
    cht  
       2022-01-06 15:46:16 +08:00
    muzuiget
        32
    muzuiget  
       2022-01-06 15:46:45 +08:00
    我不想,我直接加括号。
    gengchun
        33
    gengchun  
       2022-01-06 15:55:19 +08:00
    @crayygy 这个看具体的代码类型。

    如果是表示的是具体的业务,特别是现实中的商务订单处理这类,当然应该尽量分开。

    如果是对一张照片里的每个图素都进行一次变换操作,这么写代价就太大了。
    abersheeran
        34
    abersheeran  
       2022-01-06 23:32:08 +08:00
    我从来不考虑这个。像 Index.py 的路由,我至今记不清优先级,于是我都是

    app.router << ("/client" // client_routes) << ("/auth" // auth_routes)

    😓另外,考这个的多少有点魔怔了
    xuanbg
        35
    xuanbg  
       2022-01-07 07:10:25 +08:00
    不同语言的操作符优先级有可能不一致。反正加括号最保险,也更容易阅读。
    sprite82
        36
    sprite82  
       2022-01-07 17:47:59 +08:00
    楼主说的是 不同语言 运算符优先顺序不一样的问题,结果一堆“加括号”的评论,这不是废话吗?这是常识,就像乘号优先于加号一样。不应该讨论下为什么位运算符优先级不同语言不一样?
    seanzxx
        37
    seanzxx  
       2022-01-08 10:13:03 +08:00
    常用的语言测试了一圈
    0: Rust, Python, C, Java, Lua, Ruby, JS, PHP, Dart, C#
    1: Go, Swift

    一种常用的性能优化措施是把乘除法替换成位移
    比如
    buffer_size = 2 + int32_size * 4 替换成
    buffer_size = 2 + int32_size << 2
    如果是 Go 和 Swift ,那类似替换优雅又简洁;如果是其它语言,替换以后要加括号,还容易出 bug
    个人猜测
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   908 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 21:41 · PVG 05:41 · LAX 13:41 · JFK 16:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.