使用zsh
:
width=7.25; echo $(( width * 2 ))
:输出是14.5
width=7.5; echo $(( width * 2 ))
:输出为15.
,带有尾随点
这似乎是一个非常基本的东西,但我还没有弄清楚。15
在第二个例子中,我怎样才能只得到 ,而没有尾随的点?
使用zsh
:
width=7.25; echo $(( width * 2 ))
:输出是14.5
width=7.5; echo $(( width * 2 ))
:输出为15.
,带有尾随点这似乎是一个非常基本的东西,但我还没有弄清楚。15
在第二个例子中,我怎样才能只得到 ,而没有尾随的点?
为了去掉尾随的点,请使用参数扩展
${name%pattern}
的形式。如果结果由于近似而不是整数,那么这将没有帮助。
如果您不喜欢这个结果:
zsh
是 3 个类 Bourne shell 之一(与 ksh93 和 yash 一起),它们在算术表达式中支持整数算术和浮点算术(在(( ... ))
、$(( ... ))
和${array[...]}
大多数以数字为参数的内置函数中,就像在 ksh 中一样,这些功能就来自那里)。这些算术表达式是仿照 C 语言形成的,并且遵循基本相同的规则¹。具体来说,只涉及整数的运算会产生整数。而一旦涉及浮点数,就会提升为浮点数。
与 C 语言类似,如果数字文字包含
.
或使用工程符号 (1e-2
...) 或者是 NaN 或 Infinity² 的变体之一,则它被视为浮点数,否则为整数,因此将 a 附加.
到十进制数字序列是确保它被视为浮点常量而不是整数常量的最简单方法。例如,在 C 中,如在 zsh / ksh93³ / yash 中,
2 / 4 * 6.
产生 0。因为2 / 4
产生 0 个整数,并0 * 6.
产生0.
浮点数。因为是浮点运算,所以结果是 0.5,因为至少有一个操作数是浮点数,所以结果是 0.5,也是浮点
2. / 4 * 6
运算。3.
2. / 4
0.5 * 6
ksh93 中也一样:
或者 zsh:
zsh
除了通过添加 来保留表达式产生浮点数的信息之外.
。如果数字已经是浮点表示,则不会添加 ,.
原因如下:更一般地说,当 zsh 为您提供浮点数的十进制文本表示形式(它在内部将其存储为
double
C 类型)时,它会尝试为您提供完全忠实的表示形式,以便如果稍后在另一个算术表达式中使用该表示形式,则不会发生信息丢失,包括类型(整数与浮点数)和精度。这就是为什么除了添加该格式
.
来消除浮点数和整数的歧义之外,它还%.17g
sprintf()
在计算数字的十进制整数文本表示时使用该格式,因为 17 位是一般情况下所需的最小十进制位数,以确保保留 64 位 IEEE 754 双精度二进制数的完整精度。而这么高的精度有一个缺点,就是会暴露出十进制和二进制之间转换产生的错误。在为什么 $((0.1)) 在 zsh 中扩展为 0.10000000000000001?中对此进行了详细讨论。
现在,对于人类来说,您通常不需要看到它就
.
知道它是一个浮点数,您也不必关心它是否是浮点数。而且您不需要看到那么多的精度,因此出于显示目的和仅供人类使用,最好使用它printf
或print -f
格式化数字。awk
将以与例如使用 6 位精度格式化相同的方式打印宽度值(对于 1e-4 以下或 1e6 以上的数字,也可以切换到9.9999e-05
或1e06
)OFMT
这里的区别是,如果数字被视为整数,则无需经过格式化。使用:
如果您想保留尽可能多的精度,同时仍然删除
.
那些没有小数部分的数字。与 ksh 类似,也可以使用以下命令声明变量:
对于 ,
$x
在扩展时用句点后有 2 位数字的浮点符号表示(与指令一样%.2f
printf
)并且$y
用 6 位有效数字的工程符号表示(与%.6e
printf
指令一样),但我不认为有等效的%g
。请注意,变量的值仍然以全精度存储在内部,那些
-F
/-E
属性只会影响扩展。¹ 除了
zsh
与 ksh 相反之外,在运算符优先级方面存在一些不兼容性,但这与这个问题无关。² 请注意,与 ksh93 或 yash 或 C99 相反,它不支持诸如
0xDead.Beef
或0x123p-4
之类的浮点十六进制。³ 但请注意,ksh93 尊重语言环境的十进制基数字符;在语言环境中,它
,
代替.
,必须这样写2 / 4 * 6,