假设两个数字存储在两个不同的文件中,a.txt
并且b.txt
.
每个数字都足够大(超过 30 位),因此 所使用的数字数据类型不支持bash
。
我如何将它们添加到 shell 中?
答案1
假设它们是十进制数,你可以这样做:
paste -d + a.txt b.txt | bc
请注意,bc
非常长的数字会换行(超过 68 或 69 位数字,具体取决于实现)。使用 GNU bc
,您可以通过将环境变量设置为 0 来禁用它BC_LINE_LENGTH
,例如:
paste -d + a.txt b.txt | BC_LINE_LENGTH=0 bc
答案2
诀窍是不用于bash
执行加法1 .
首先,将每个数字读入一个单独的变量中。这假设文件包含只有一个数字并且没有其他信息。
read a <a.txt
read b <b.txt
然后使用bc
计算器得到结果:
bc <<<"$a + $b"
bc
是一种“任意精度算术语言和计算器”。
要将结果存储在变量中c
:
c="$( bc <<<"$a + $b" )"
如果语法感觉很奇怪(它被称为“here-string”,是 POSIX shell 语法和其他一些 shell<<<
支持的扩展),您可以改为使用将添加内容发送到:bash
printf
bc
printf '%s + %s\n' "$a" "$b" | bc
并将结果c
再次存储在:
c="$( printf '%s + %s\n' "$a" "$b" | bc )"
1 用于bash
执行两个极大数字的加法需要在bash
脚本中实现执行以下操作的例程任意精度算术。这是完全可行,但很麻烦并且不必要,因为每个 Unix 都附带bc
,它已经以相对简单且易于访问的方式为您提供了此服务。
答案3
既史蒂芬和库萨罗南达说,“真的,只需使用 bc”,但如果你真的想使用巴什另外,这是一个起点(仅限正整数)——我将把它作为读者实现小数和负数的练习:
function arbadd {
addend1=$1
addend2=$2
sum=
bcsum=$(echo $addend1 + $addend2 | BC_LINE_LENGTH=0 bc)
# zero-pad the smallest number
while [ ${#addend1} -lt ${#addend2} ]
do
addend1=0${addend1}
done
while [ ${#addend2} -lt ${#addend1} ]
do
addend2=0${addend2}
done
carry=0
for((index=${#addend1}-1;index >= 0; index--))
do
case ${carry}${addend1:index:1}${addend2:index:1} in
(000) carry=0; sum=0${sum};;
(001|010|100) carry=0; sum=1${sum};;
(002|011|020|101|110) carry=0; sum=2${sum};;
(003|012|021|030|102|111|120) carry=0; sum=3${sum};;
(004|013|022|031|040|103|112|121|130) carry=0; sum=4${sum};;
(005|014|023|032|041|050|104|113|122|131|140) carry=0; sum=5${sum};;
(006|015|024|033|042|051|060|105|114|123|132|141|150) carry=0; sum=6${sum};;
(007|016|025|034|043|052|061|070|106|115|124|133|142|151|160) carry=0; sum=7${sum};;
(008|017|026|035|044|053|062|071|080|107|116|125|134|143|152|161|170) carry=0; sum=8${sum};;
(009|018|027|036|045|054|063|072|081|090|108|117|126|135|144|153|162|171|180) carry=0; sum=9${sum};;
(019|028|037|046|055|064|073|082|091|109|118|127|136|145|154|163|172|181|190) carry=1; sum=0${sum};;
(029|038|047|056|065|074|083|092|119|128|137|146|155|164|173|182|191) carry=1; sum=1${sum};;
(039|048|057|066|075|084|093|129|138|147|156|165|174|183|192) carry=1; sum=2${sum};;
(049|058|067|076|085|094|139|148|157|166|175|184|193) carry=1; sum=3${sum};;
(059|068|077|086|095|149|158|167|176|185|194) carry=1; sum=4${sum};;
(069|078|087|096|159|168|177|186|195) carry=1; sum=5${sum};;
(079|088|097|169|178|187|196) carry=1; sum=6${sum};;
(089|098|179|188|197) carry=1; sum=7${sum};;
(099|189|198) carry=1; sum=8${sum};;
(199) carry=1; sum=9${sum};;
esac
done
if [ $carry -eq 1 ]
then
sum=1${sum}
fi
printf "Sum = %s\n" "$sum"
}
我把bc
比较留在那里,但为了比较而注释掉了。