紀元前

紀元前

私は、最初の数字の各数字の合計を提供し、2番目の数字の累乗を計算するスクリプト(script1.sh)を作成しようとしています。だから

./script1.sh 12345 2

出力しなければならない55

(1+4+9+16+25=55だから)

または./script1.sh 3706907995955475988644381 25

出力する必要があります3706907995955475988644381

私はスクリプトを書いていますが、いくつかのケースでは否定的な結果が出ていますが、どのようにこれが起こるのかわかりません。

例えば

./script1.sh 3706907995955475988644380 25

出力

-2119144605827694052

私のスクリプト:

#!/bin/bash
sum=0

value=$1

arr=()
for ((i = 0; i < ${#value}; i++)); do
    arr+=(${value:$i:1})
done

for x in "${arr[@]}"; do
    sum=$(($sum+(x**$2)))
done
echo $sum

答え1

シェル算術は、bashCコンパイラがサポートする最も広い整数型を使用します。ほとんどの最新のシステム/ Cコンパイラでは、これは64ビット整数であるため、「のみ」は-9223372036854775808から9223372036854775807までの数字を含む範囲をカバーします。これを行うには、bcなどの他のツールを使用する必要があります。

#!/bin/bash

num1=$1
num2=$2
sum=0

for (( i=0; i<${#num1}; i++ )); do
    n=${num1:$i:1}
    sum=$( bc <<<"$sum + $(bc <<<"${n}^$num2")" )
done

echo "$sum"

答え2

ストラップが短いawkスクリプト:

sum_powered.awkスクリプト:

#!/bin/awk -f
BEGIN{
    split(ARGV[1], a, "");
    pow = ARGV[2];
    for (i in a) sum += a[i] ** pow;
    print sum;
}

使用法:

$ ./sum_powered.awk 12345 2
55

$ ./sum_powered.awk 3706907995955475988644381 25
3706907995955475217645568

新しいエントリに実行権限を追加する必要があるかもしれません。アッ実行前のスクリプト:

$ chmod +x sum_powered.awk 

答え3

25桁の3706907995955475988644381結果()で数学演算を実行することは、ほとんどのシェル実装機能を超えることです。実際、シェル算術はC算術と非常によく似ています。 Cでは、符号付き整数はオーバーフロー時に符号を反転します。 64ビットシステムで使用される一般的な最も長いシステム整数の値制限は63個の2進数(整数の符号を定義する別のビット)なので、2進数で63個の1または16進数で0efff ffff ffff ffffは数値$(((1 <<63) - 1 )) または 9223372036854775807(19桁)。負の制限は-9223372036854775808です。

25桁の数字は19桁の整数に入ることができないため、以下のようにオーバーフローします。C符号付き整数オーバーフロー:記号を変更して(ほとんどのコンピュータで):

$ echo "$(( 9223372036854775807 + 1 ))"
-9223372036854775808

紀元前

a(スタンドアロン)ユーティリティが「任意の精度数学」(事前設定された長さ制限のない数値)を提供できる最も低いレベルの言語はbcです。 BCでは、全体的な要件を実装することは難しくありません。

x=12345
y=2
scale=0;
s=0;
while (x>0) {
              b=x%10;
          x/=10;
          s+=b^y
        };
s
quit

ファイルに書き込み(仮定digpower.bc)し、次のコマンドを実行します。

$ bc -q digpower.bc
55

ファイル全体を処理時間変数のみを含め、スケールを元の値として返す関数に変換します。

define d(x,y){
    auto s,b,u; s=scale;
    while (x>0) { b=x%10; x/=10; u+=b^y }
    scale=s; return(u) };

この場合、次のようにbcを呼び出します。

$ bc -q digpower.bc <<<"d(12345,2)"
55

$ echo "d(3706907995955475988644381,25)" | bc digpower.bc
3706907995955475988644381

Python

無限の(コンピュータメモリのみ)整数を使用する次の高級言語(共通lispをスキップする)はPythonです。

$ python3 -c 'x=12345;y=2;s=0;
while (x>0): b=x%10;x//=10;s+=b**y                        
print(s)'
55

ほとんどの他の言語はawk

アッ

内部のすべての数字はawk浮動小数点数として格納されます。デフォルトでは、awkは53ビットの歌手を使用します。 53ビット歌手の一般的な制限は16ビットです。一部の特定の浮動小数点数では、17ビットまたは18ビットが正確かもしれません。

$ awk -vx=12345 -vy=2 'BEGIN{s=0;while(x>0){b=x%10;x=int(x/10);s+=b^y}; print(s)}'
55

しかし、(他の値と同じコード):

$ awk -vx=3706907995955475988644381 -vy=25 'BEGIN{s=0;while(x>0){b=x%10;x=int(x/10);s+=b^y}; print(s)}'
2989038141653481752100864

浮動小数点数の内部表現が16桁以降は完全に間違っているため、これは明らかに間違っています。ただ見せるなら:

$ awk -vx=3706907995955475988644381 'BEGIN{print(x);print(x+0)}'
3706907995955475988644381
3706907995955475754516480

この間違いはより大きな間違いにつながります。

awkがbignumにコンパイルされている場合(awk --versionの出力に「GNU MPFR」が含まれている場合)、GNU awkの代替案は浮動小数点仮数の数を増やすことです。

$ awk -M -v PREC=100 -vx=3706907995955475988644381 -vy=25 'BEGIN{s=0;while(x>0){b=x%10;x=int(x/10);s+=b**y}; print(s)}'
3706907995955475988644381

25個の10進数にはおよそ2進数25*log(2)/log(10)または83個の歌手が必要です(正確な答えは説明に時間がかかります)。 100を使用すると、十分なマージンが提供されます。

関連情報