기원전

기원전

나는 첫 번째 숫자의 각 숫자의 합을 제공하고 두 번째 숫자의 거듭제곱을 계산하는 스크립트(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개의 이진수(정수의 부호를 정의하는 또 다른 비트)이므로 이진수로 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

파이썬

무한한(컴퓨터 메모리만으로) 정수를 사용하는 다음 고급 언어(공통 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개의 십진수에는 대략 25*log(2)/log(10)이진수 또는 83개의 가수가 필요합니다(정확한 답변은 설명하는 데 시간이 더 걸립니다). 100을 사용하면 충분한 마진이 제공됩니다.

관련 정보