MATLAB에서 변수는 기본적으로 정말 배정 밀도입니까?
이 질문은 내가이 질문을 더 조사한 후에 발견 한 이상한 점에서 나왔다 .
저는 항상 MATLAB 변수 가 기본적으로 배정 밀도라는 것을 이해 합니다. 따라서 소수점 자리 20 자리가있는 변수를 선언하는 것과 같은 작업을 수행 한 다음을 수행합니다.
>> num = 2.71828182845904553488;
>> class(num) % Display the variable type
ans =
double
부동 소수점 상대 가 10-16 정도 이기 때문에 마지막 4 자리는 무시 될 예상합니다 .
>> eps(num)
ans =
4.440892098500626e-016
소수점 이하 16 자리 이상의 숫자를 표시하면 ( 또는을 사용하여 ) 다음과 같이 표시됩니다.fprintf
sprintf
>> fprintf('%0.20f\n', num)
2.71828182845904550000
>> sprintf('%0.20f', num)
ans =
2.71828182845904550000
즉, 17에서 20까지의 숫자는 모두 0입니다.
그러나 기호 도구 상자num
의 variable-정밀도 산술 함수 에 전달 하면 (21)의 정밀도를 자리 사용하여 숫자를 나타내 도록 지시하는 것이 이상해 집니다.
>> vpa(num, 21)
ans =
2.71828182845904553488
뭐?! 마지막 4 자리 숫자가 다시 번역습니다! 내가 입력 한 원래 숫자가 배정 밀도 변수로 저장 될 때 잃어 버려야하지 num
보장? 에 num
전달 될 때 배정 밀도 변수가 되었기 때문에 그것이 무엇인지 vpa
어떻게 vpa
알 수 있습니까?
어떤 일이 일어나고 있는지에 대한 나의 가장 좋은 추측은 num
배정 밀도 변수가 처리 할 수있는 것보다 소수점 이후 더 많은 자릿수를 숫자로 초기화했기 때문에 MATLAB이 내부적으로 배정 밀도보다 더 표현한다는 것입니다. 이것이 일어나고있는 일입니까? 아니면 다른 일이 일어나고 있습니까?
보너스 : 위의 편두통이없는 경우 여기에 추가 혼란의 원인이 있습니다 ...
>> num = 2.71828182845904553488; % Declare with 20 digits past the decimal
>> num = 2.718281828459045531; % Re-declare with 18 digits past the decimal
>> vpa(num, 21)
ans =
2.71828182845904553488 % It's the original 20-digit number!!!
그들은 복식입니다. vpa()
단순히 부동 소수점 상대 정확도, non-유효 숫자 이상-display하기 위해 선택하고있다 printf()
그리고 disp()
그들을 zero-잘라 내기 또는.
초기화하기로 선택한 리터럴 num
은 실제 double 값의 확장 초기화 출력에서 복사하여 전면 초기화 초기화 초기화 하기로 선택한 리터럴이 이진 double 값의 정확한 십진수 확장 이기 원래 때문에 4 자리 만 되돌립니다. 다른 질문에서. "BONUS"는 나와있는 것처럼 다른 가까운 값에 작동하지 않습니다.
보다 정확하게는 Matlab의 모든 숫자 리터럴은 double 유형의 값을 생성합니다. 그들은 그들에게 십진수 값에 가장 가까운 이진 double 값으로 변환됩니다. 실제로 이중 유형의 한계를 초과하는 리터럴의 숫자는 자동으로 삭제됩니다. vpa
다른 질문의 포스터 가 e = ...
명령문에서 했던 것처럼 대신 새 변수를 만들면 이전의 결과를 직접 처리하는 리터럴에서 값을 초기화하는 것입니다.
여기서 차이점은 출력 형식에만 있습니다. 제 생각에 vpa()
이중 설명 이진 double을 정확한 값으로 취급하는 것입니다. 주어진 이진 가수 지수 값에 대해 임의의 많은 소수 자리에 해당하는 소수를 계산할 수 있습니다. 고정 크기 데이터 유형에서와 같이 2 진 값에 있고 ( "너비")가있는 경우 소수의 소수만 유효합니다. printf()
Matlab의 기본 앰프는 출력을 자르거나 중요하지 않은 숫자를 0으로 표시하여 처리합니다. vpa()
한계의 한계를 무시하고 요청한만큼 소수점 이하 자릿수를 계속 계산합니다.
추가는 다음 숫자는 가까운 10 진수 값을 생성하기 위해 다른 값으로 대체 할 모두 이진 이중 값으로 "반올림"점에서 가짜입니다.
그것을 작성 방법이 있습니다. 이러한 x 값은 double로 저장 될 때 모두 동일하며 모두 동일하게 표시 vpa()
됩니다.
x = [
2.7182818284590455348848081484902650117874145507812500
2.7182818284590455348848081484902650117874145507819999
2.7182818284590455348848
2.71828182845904553488485555555555555555555555555555
exp(1)
]
unique(x)
이를 시연하는 또 다른 방법이 있습니다. 서로 매우 가까운 두 개의 복식이 있습니다.
x0 = exp(1)
x1 = x0 + eps(x0)
vpa(x0)
및 vpa(x1)
16 자리 지나서 많은 차이 출력을 생성한다. 그러나 double value 생성 할 수 안 x
그런 사이 vpa(x)
에 진수 표현 생산 vpa(x0)
과 vpa(x1)
.
(업데이트 : Amro fprintf('%bx\n', x)
는 기본 이진 값의 정확한 표현을 16 진수 형식으로 표시하는 데 사용할 수 있다고 지적 합니다.이를 사용하여 리터럴이 동일한 double에 매핑되는지 확인할 수 있습니다.)
나는 의심 vpa()
이 두 배 이상의 정밀도를 가지고있는 상징적 인 도구 상자에서 다른 매트랩 유형을 지원 다형 정확한 값으로의 입력을 처리하고 있기 때문에 동작합니다 이런 식으로. 이러한 값은 왜 숫자 리터럴, 이외의 방법에 의해 초기화 될 필요가 sym()
입력과 같은 문자열을 얻어 vpa(exp(1))
다르다 vpa(sym('exp(1)'))
.
말이 되나? 긴 바람에 죄송합니다.
(참고로 Symbolic Toolbox가 없으므로 vpa()
직접 테스트 할 수 없습니다 .)
먼저 :
sprintf와 fprintf는 예를 들어 MATLAB 2018에서 MATLAB의 다른 버전에서 다른 동작을하는 것으로 보입니다.
num=2.7182818284590666666666;
sprintf('%0.70f', num)
ans =
'2.7182818284590668511668809514958411455154418945312500000000000000000000'
둘째 :
부동 소수점 숫자
MATLAB®은 배정 밀도 또는 단 정밀도 형식으로 부동 소수점 숫자를 나타냅니다. 기본값은 배정 밀도이지만 간단한 변환 함수를 사용하여 임의의 숫자 단 정밀도를 만들 수 있습니다.
배정 밀도 부동 소수점
MATLAB은 배정 밀도에 대해 IEEE® Standard 754에 따라 배정 밀도 (또는 배정 밀도) 데이터 유형을 생성합니다. double로 저장된 모든 값에는 64 비트가 필요하며 아래 표에 표시된대로 형식이 지정됩니다.
비트 : 63
용도 : 부호 (0 = 양수, 1 = 음수)비트 : 62 ~ 52 사용법 : 지수, 1023 바이어스
비트 : 51 ~ 0 사용법 : 숫자 1.f의 분수 f
252 = 4,503,599,627,370,496과 253 = 9,007,199,254,740,992 사이에서 표현 가능한 숫자는 정확히 정수입니다. 다음 범위 인 253에서 254의 경우 모든 값에 2를 곱하므로 표현 가능한 숫자는 짝수 등입니다. 반대로 이전 범위 인 2 ^ 51에서 2 ^ 52의 경우 간격은 0.5입니다.
2 ^ n에서 2 ^ n + 1 범위에있는 숫자의 일부로서의 간격은 2 ^ n−52입니다. 따라서 가장 가까운 표현 가능한 숫자 (기계 입실론)로 숫자를 반올림 할 때의 최대 상대 반올림 오류는 2 ^ −53입니다.
따라서 n = 1 (2 ^ 1 <= num <= 2 ^ 2) 인 경우 간격은 2 ^ -51입니다.
숫자를 표시하는 sprintf 및 sprintf 알고리즘이 까다 롭고 MATLAB Double 유형이 IEEE 표준을 기반으로한다고 가정하는 것이 안전하다고 생각합니다.
VPA 정보 :
vpa는 가드 디지트를 사용하여 정밀도 유지
Digits 함수의 값은 사용되는 최소 유효 자릿수를 지정합니다. 내부적으로 vpa는 숫자가 지정한 것보다 더 많은 숫자를 사용할 수 있습니다. 이러한 추가 숫자는 후속 계산에서 반올림 오류를 방지하기 때문에 보호 숫자라고합니다.
4 개의 유효 자릿수를 사용하여 수치 적으로 대략 1/3입니다.
a = vpa(1/3, 4)
a =
0.3333
20 자리 숫자를 사용하여 대략적인 결과 a를 구하십시오. 결과는 도구 상자가 a를 계산할 때 내부적으로 4 자리 이상을 사용했음을 보여줍니다. 반올림 오류로 인해 결과의 마지막 숫자가 올바르지 않습니다.
vpa(a, 20)
ans =
0.33333333333303016843
발생할 수있는 문제는 간격, 자릿수 알고리즘 및 반올림 문제 때문입니다.
예를 들어 matlab 2018 a 사용 :
sprintf('%0.28f', 8.0)
ans =
'8.0000000000000000000000000000'
그러나:
sprintf('%0.28f', 8.1)
ans =
'8.0999999999999996447286321199'
숫자가 2 ^ 3과 2 ^ 4 사이이므로 간격은 2 ^ -49 (= 1.77 e-15)이므로 소수점 15 자리까지 유효하며
sprintf('%0.28f', 64.1)
ans =
'64.0999999999999943156581139192'
숫자가 2 ^ 6과 2 ^ 7 사이이므로 간격은 2 ^ -46 (= 1.42 e-14)이므로 소수점 14 자리까지 유효합니다.
'ProgramingTip' 카테고리의 다른 글
포인터를 비교하는 방법? (0) | 2020.11.03 |
---|---|
Python으로 사용 가능한 com 포트 텍스트 (0) | 2020.11.03 |
e.getMessage ()와 e.getLocalizedMessage ()의 차이점 (0) | 2020.11.02 |
Brew Doctor-“경고 : / usr / local / include에서 추출되지 않은 헤더 파일을 발견 했습니까?”? (0) | 2020.11.02 |
.NET 앱용 링커의 현황 (일명 "링크가 있습니다"2009 년판) (0) | 2020.11.02 |