问题描述
如何划分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
P.S。
并且,有一种方法可以安全地将int64
强制转换为int
,因此结果将是int
而不是int64
,并进行溢出检查。>
解决方法
对此issue中的int64
划分已有一些讨论,可能可以对当前状态进行一些改进。从以上问题开始:
- 在
int64
之间没有stdlib浮点分隔的一个很好的理由是,这可能会导致精度损失,因此用户应将int64
显式转换为float
- 在stdlib中仍然存在
float
类型之间的int
划分 - 在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 .:如您所见,上述标准转换具有范围检查功能
,显然,在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
关于从int64
到int
的转换,我不确定这是否有意义,因为大多数平台都将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来避免数月至数秒的增加(或更安全的方式)。