3

从秒 ( )计算分钟 ( m) 和小时 ( ) 的工作原理与我预期的一样:hss

s = 14200
h = s/3600 #=> 3
m = (s % 3600 ) / 60 #=> 56

但是,如果s是负数,我会得到不同的结果:

s = -14200
h = s/3600 #=> -4
m = (s % 3600 ) / 60 #=> 3

我不明白为什么当我以相同的秒数开始时会得到 -4 小时 3 分钟,只是负数。

这里发生了什么?有什么方法可以让我获得一致的正负值结果?如果结果是否定的,除了使用s.abs % 3600和修改结果之外?s

4

3 回答 3

2

你可以想到像这样实现的 ruby​​ 中的整数除法——

给定ab,ruby 找到整数解, q b + m = a使得

  1. m是相同的符号b
  2. 的值m尽可能小(接近于零)。

这两条规则为q( a / b) 和m( a % b) 提供了独特的解决方案。

在您的第一种情况下,a是 14200 和3600。b遵循q b + m = a这些规则的唯一解决方案是- 尝试一下。q = 3m = 1600

> 3 * 3600 + 1600
# => 12400

这是唯一的解决方案吗?怎么样q = 4?然后

4 * 3600 + m = 12400
m = -2000

不……m现在不仅比以前更大,而且甚至是错误的标志(还记得第一条规则吗?)

怎么样q = 2

2 * 3600 + m = 12400
m = 5200

不......我们的第一个解决方案m是更小。q因此,和可能的唯一值m是 3 和 1600。

现在让我们试试你的第二种情况——a现在-12400b现在3600。唯一的解决方案是q = -4b = 2000

让我们检查。

> -4 * 3600 + 2000
# => -12400

有用!

让我们快速检查其他值q- 让我们尝试 -3,如果我们与第一个示例进行比较,这是“显而易见的”答案:

-3 * 3600 + m = -12400
m = -1600

好吧……嗯,m这里比以前“更小”了……所以它符合规则#2。但是规则 #1 说它m必须与 ... 的符号相同,b所以我们不会接受 的负值m

因此,唯一唯一的解决方案是q = -4m = 2000

您的问题中的其他两个部门应该从这里清楚。

为了获得您似乎期望的结果,您应该使用-3600而不是3600您的小时红利。

于 2013-06-26T23:57:01.310 回答
1

必须注意%负数。他们很狡猾:

irb(主):011:0> 14200 % 3600
=> 3400
irb(主):012:0> -14200 % 3600
=> 200
于 2013-06-26T23:45:25.083 回答
1

14200 除以 3600 大约是 3.9,在整数算术中被截断为 3。

-14200 除以 3600 大约是 -3.9,在整数算术中被截断为 -4。

使用%, 负数从第二个值“倒数” - 当您牢记这一点时,您的结果将非常有意义。例如:

 1 % 6 # => 1
-1 % 6 # => 5

更新:我认为如果秒数为负数,您需要准确考虑您想要什么。你可能会做这样的事情:

dir = "from now"

if s < 0
  dir = "ago"
  s = -s
end

h = s / 3600
m = (s % 3600 ) / 60

puts "s represents #{h} hours and #{m} minutes #{dir}"

做什么实际上取决于代码的更大上下文中的确切含义h和含义,以及该上下文中负值的确切含义。ms

在另一种情况下,也许您希望hm具有与正数相同的绝对值,s但具有与 相同的符号s

sign = s < 0 ? -1 : 1
s = s.abs

h = s / 3600 * sign
m = (s % 3600 ) / 60 * sign

由您决定什么适合您的情况。

于 2013-06-26T23:48:15.407 回答