【问题标题】:Time maximums in Windows shell and Why?Windows shell 中的时间最大值,为什么?
【发布时间】:2019-06-07 12:35:47
【问题描述】:

我在Windows Batch Scripting做了一个简单的倒计时

@ECHO OFF
MODE con: cols=13 lines=2
COLOR 4f
TITLE Countdown Timer
SET /p m=? Minutes:
SET /a s = 60 * m
FOR /l %%a in (%s%,-1,1) do (
  ECHO %%a/%s%
  PING -n 2 127.0.0.1 >NUL 2>&1
  CLS
)
IF ERRORLEVEL 1 EXIT
CSCRIPT alert.vbs
EXIT

我注意到以下几点:

  1. 我可以使用的最大正是eighth Mersenne prime:2147483647(2147483647 seconds to years at DuckDuckGo),但是
  2. 如果我使用乘数60分钟 开始倒计时,则可接受的最大整数为1037950429.99999999

通过研究了解为什么(?),我提出了这个问题。

【问题讨论】:

  • 它与时间测量的限制无关。它与整数的精度有关,在命令或批处理文件 IIRC 中以 32 位签名。
  • 不要在= 周围批量使用空格,如SET /a s = 60 * mDon't use ping to sleep。而 2147483647 只是 2³¹-1,它是最大的 32 位整数(cmd 使用)。此外set /a 不支持浮点运算,因此set /a 1037950429,99999999*60set /a 99999999*60 完全相同。如果要使用 64 位 int 或 double,则必须使用其他脚本语言,如 powershell 或 VBS
  • 另外,任意决定从任何基点开始一定的分钟数是错误的。您已将其(错误地)与 1973 年 6 月 10 日 9:00 相关联,但这并不准确。这只是一定的分钟数——除了你决定分配的时间之外,这些分钟没有开始参考点。 IOW,如果我现在启动一个计时器并让它运行 10 分钟,那么该计时器的起始参考点不是 1970 年,而是我启动计时器的时间。您的 1973 表示 1973 年期间,而不是从特定起点算起的 1973 年。 2019+1973有效。
  • 要获得 32 位精度的最大正数,请在命令提示符处输入 set /A 0x7FFFFFFF。对于最小负数,输入set /A 0x80000000
  • 感谢你们出色的 cmets,现在我有我所有的答案了!按日期付款很有趣;)

标签: windows batch-file cmd


【解决方案1】:

cmd.exe(以及它的set /a内部命令)只使用32位整数,因此它可以表示的最大值是2147483647 = 232 - 1

所有数字都必须在 32 位有符号整数范围内(-2,147,483,648 到 2,147,483,647)才能使用 PowerShell 或 VBScript 处理更大的数字。

https://ss64.com/nt/set.html

这是计算机中非常常见的常量,因为我们几乎都使用 32 位 int。由于位宽的选择,与梅森素数的相关性纯属偶然

从上面的链接你可以看到逗号是一个分隔符,就像在类C语言中一样,不是小数点。事实上,我从未见过像书面语言那样使用逗号作为小数点的编程语言。

,逗号分隔表达式set /a "_num=2,_result=_num*5"

如果您运行 set /?,您将在优先级表中看到逗号

The /A switch specifies that the string to the right of the equal sign
is a numerical expression that is evaluated.  The expression evaluator
is pretty simple and supports the following operations, in decreasing
order of precedence:

()                  - grouping
! ~ -               - unary operators
* / %               - arithmetic operators
+ -                 - arithmetic operators
<< >>               - logical shift
&                   - bitwise and
^                   - bitwise exclusive or
|                   - bitwise or
= *= /= %= += -=    - assignment
  &= ^= |= <<= >>=
,                   - expression separator

这意味着1037950429,999999999*60 只是两个表达式,一个值为 1037950429,一个值为 999999999*60,溢出 32 位 int 并返回一个负值,如您所见

C:\Users\>set /a 1037950429,999999999*60
-129542204
C:\Users\>set /a 999999999*60
-129542204
C:\Users\>set /a 1037950429,99999999*60
1705032644
C:\Users\>set /a 99999999*60
1705032644
C:\Users\>set /a 1037950429.999999999*60
Missing operator.

即使您想对诸如 1037950429.999999999 之类的浮点值进行操作,那么您也不走运,因为它超过了 VBS 和 PowerShell 中最大的 binary 浮点类型的精度,它是IEEE-754 double precision,只能精确到~15 位十进制数字。 PowerShell 确实有一个 128-bit decimal floating-point type(继承自 .NET's decimal),但在这种情况下会有所帮助

PS C:\Users> 1037950429.999999999d*60
62277025799.999999940

但是 Windows 已经有一个倒计时命令:timeout。除非您想对其进行更多控制,否则没有理由重新实现它

请注意,set a = b 批处理意味着将字符串 b 与前面的空格分配到名为 %a % 的变量中。 set 命令中的空格很重要,因此不建议在 = 运算符周围使用空格。见

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-25
    • 2015-05-19
    • 2012-10-25
    • 2010-12-07
    • 2020-09-06
    • 1970-01-01
    相关资源
    最近更新 更多