【问题标题】:How to divide int64 in Nim?如何在 Nim 中划分 int64?
【发布时间】:2020-09-17 06:01:49
【问题描述】:

int64怎么分?

let v: int64 = 100
echo v / 10

错误Error: type mismatch: got <int64, int literal(10)>

完整示例

import math

proc sec_to_min*(sec: int64): int = 
  let min = sec / 60 # <= error
  min.round.to_int

echo 100.sec_to_min

附言

还有,有没有办法安全地将int64 转换为int,所以结果将是int 而不是int64,并检查溢出。

【问题讨论】:

    标签: nim-lang


    【解决方案1】:

    在这个issue 中已经对int64 划分进行了一些讨论,并且可能可以对当前状态进行一些改进。从上述问题:

    • 在 stdlib 中没有 int64 之间的浮点除法的一个很好的理由是它可能会导致精度损失,因此用户应该明确地将int64 转换为 float
    • 不过,float 类型之间的int 划分仍然存在于 stdlib 中
    • 在 64 位系统上 int int64(因此在 64 位系统中 int64 之间存在划分)

    对于您的用例,我认为以下 (playground) 应该可以工作(最好使用 div 而不是进行浮点除法然后四舍五入):

    import math
    
    proc sec_to_min*(sec: int64): int = sec.int div 60
    
    echo 100.sec_to_min
    
    let a = high(int64)
    echo a.int  # on playground this does not raise error since int is int64
    echo a.int32  # this instead correctly raises error
    

    输出:

    1
    9223372036854775807
    /usercode/in.nim(9)      in
    /playground/nim/lib/system/fatal.nim(49) sysFatal
    Error: unhandled exception: value out of range: 9223372036854775807 notin -2147483648 .. 2147483647 [RangeError]
    

    P.S.:正如您在上面看到的,标准转换具有范围检查

    【讨论】:

      【解决方案2】:

      显然,int64 类型之间的划分是非常危险的,因为它会引发大量的自行车脱落,但至少您可以创建自己的运算符:

      proc `/`(x, y: int64): int64 = x div y
      
      let v: int64 = 100
      echo v / 10
      

      或者

      proc `/`(x, y: int64): int64 = x div y
      
      import math
      
      proc sec_to_min*(sec: int64): int = 
        int(sec / 60)
      
      echo 100.sec_to_min
      

      关于int64int 的转换,我不确定这是否有意义,因为大多数平台将int 作为int64 的别名运行。但是当然你可以在 32 位平台上编译/运行,损失会很惨重,所以你仍然可以做运行时检查:

      let a = int64.high
      
      echo "Unsurprising but potentially wrong ", int(a)
      
      proc safe_int(big_int: int64): int =
        if big_int > int32.high:
          raise new_exception(Overflow_error, "Value is too high for 32 bit platforms")
        int(big_int)
      
      echo "Reachable code ", safe_int(int32.high)
      echo "Unreachable code ", safe_int(a)
      

      此外,如果您遇到令人困惑的分钟、小时、天转换,您可能需要查看 into distinct types 以避免将月份添加到秒(或者以更安全的方式这样做)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-11-06
        • 2023-01-10
        • 2019-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多