我在 Linux 机器上有一个文件,每行一个数字:
3073771824
1513517589
4982173058
1539400944
3175320163
5247018359
14359014635
....
我怎样才能将每个数字乘以 1.03(3%),然后将结果四舍五入,去掉逗号?例如:
3073771824 * 1,03 = 3165984978,72 | I would have the result 3165984979
1513517589 * 1,03 = 1558923116,67 | I would have the result 1558923117
....
我知道 awk 可以四舍五入:
echo 2.5 | awk '{print int($1+0.5)}'
四舍五入为 3,但是有“。”,没有“,”。
假设您的数字位于文件中
numbers
,并且您的locale
文件使用,
小数点,例如fr_FR.UTF-8
。我还添加了10000000000
作为您的源数字之一,以证明整数结果不会向上舍入:如果输入数字可以为负数,则舍入代码需要更复杂,以便舍入到远离零的位置。如果这可能是一个问题,请告诉我,我会提供代码来解决这个问题。
结果,包括调试列,使用您的数据
无需调试,使用您的数据的结果
删除或注释掉该
printf
行以删除两个调试列。awk
如果必须,您可以通过删除注释并连接剩余的行将命令合并到一行中。现在,关于语言环境。无论语言环境如何
awk
,程序都希望其数字常量用作.
小数点;这是语法要求。例如,print 3,1
打印两个用空格分隔的值 (3 1
),但print 3.1
打印单个十进制值 (3.1
)。如果您使用的是 GNU,
gawk
您可以指定-N
标志(--use-lc-numeric
)让其读取和写入数据值,并使用您的语言环境将字符串转换为数字:但是,在您的问题中,您正在读取和写入整数值,因此语言环境的小数点并不相关。
使用Miller:
要将数字四舍五入为大整数,可以使用以下命令。
要清楚的是,在
echo 2.5 | awk '{print int($1+0.5)}'
您的问题中,awk 代码不是向上舍入到,3
而是先相加0.5
,然后向下舍入到 3(但已经是 3,因此int()
实际上没有舍入)。如果您以 开始,2.4
而不是,2.5
结果将是2
,这3
与您预期的向上舍入不同,因为int()
总是向下舍入。使用任何 awk:
如果您在语言环境中使用
,
而不是.
作为小数点,则可以在计算中使用1,03
而不是,1.03
但我不建议这样做(我建议LC_ALL=C
默认使用),因为这需要在不同的 awk 变体中使用不同的代码并且并不像听起来那么简单,例如使用 GNU awk 我们需要添加-N
以告诉 gawk 为此使用您的语言环境,然后将其写1,03
为字符串"1,03"
而不是文字数字,并依靠在算术上下文(乘法)中使用它将其转换为数字,因为文字,
在 awk 脚本中意味着不同的东西:有关更多信息,请参阅https://www.gnu.org/software/gawk/manual/gawk.html#Locale-influences-conversions 。
不过,一般来说,您要求的是一个
ceil()
(用于“上限”)函数,如上所示。当您寻找任何类型的舍入函数时,在示例中包含零和负数非常重要,因为很容易出错,因此使用此输入文件:我们可以测试一个
ceil()
函数:以及相反的
floor()
函数:上述方法有效,因为
int()
截断为零(来自 GNU awk 手册):因此
int()
,如果负数已经实现了上限函数的要求,即向上舍入,而如果int()
向下舍入为正数,则只需在结果中加 1。我
0.000001
在样本中使用了 等,以避免人们在测试添加一些数字(如0.9
然后int()
ing)的解决方案时出现假阳性结果。另请注意,
ceil()
可以缩写为:但是为了清晰起见(结果是 1 还是 0 并不明显
x>int(x)
)并且为了提高效率(只调用int()
一次而不是两次),我按照上面的方法编写了它。您可以使用一个脚本,其中数字是您的输入。以下是一个有用的函数示例。
我当然偏向于使用 Perl,因为它通常是我做事情的首选工具,但除了使用 Bash 本身或更简单的工具(如 )之外,它们本身无法处理舍入(当然它仍然可以轻松实现,但仍然如此),Perl 可能是使用模块的
bc
最简单方法。由于 Perl 的工作方式,数字前面的填充将自动且优雅地处理:ceil()
POSIX
11
如果您希望保留填充(如果结果数字可能超过 11 位,则需要进行调整):使用Raku(以前称为 Perl_6)
Raku 的使用方式与 @kos 提供的出色 Perl 答案类似。Raku 的
ceiling
例程是内置的,因此无需在命令行调用任何模块。put
调用会为您添加换行符,并且在第一个示例中不需要额外的括号put
。示例输入:
示例输出:
这就提出了一个问题:如果在输入中发现非整数该怎么办。跳过该行是最简单的方法,但是(如果这会导致列数据错位),可以使用“NaN”之类的占位符。下面演示了两种修复方法(强制转换
+$_
和测试):https://docs.raku.org/routine/ceiling
https://raku.org
我已经很久很久没有使用过了
awk
,而且我学习整数数学的时间就更长了。您必须检查您的数字是否没有超出限制,但是......
x
将返回四舍五入后的 103% 的整数值。如果需要从零开始舍入并且可能一开始就有负值,请使用一些逻辑减去99 而不是加 99(对于正值)。
简单示例:
用一些数字自己尝试一下。
另外,研究实用程序
dc
和bc
两个简单的计算器程序。对于这种简单的数据转换,这些可能比处理丰富的内容更容易awk
。