플로트 분할을 할 때 이중으로 주조하고 뒤로 주조할 때 정확도가 향상됩니까?
두 팔로잉의 차이점은 무엇입니까?
float f1 = some_number;
float f2 = some_near_zero_number;
float result;
result = f1 / f2;
그리고:
float f1 = some_number;
float f2 = some_near_zero_number;
float result;
result = (double)f1 / (double)f2;
저는 특히 Float에서 작동할 때 +infinity를 생성할 수 있는 매우 작은 f2 값에 관심이 있습니다.정확한 정보를 얻을 수 있습니까?
이런 종류의 배역을 사용하기 위한 몇 가지 실용적인 지침도 좋을 것 같습니다.
IEEE 754 이진 부동 소수점 산술을 가정하겠습니다.float
32비트 그리고double
6트.
일반적으로 계산을 하는 것은 장점이 없습니다.double
, 경우에 따라서는 두 번의 반올림을 통해 상황을 악화시킬 수도 있습니다.
전환시점float
.double
정확합니다. , NaN, 영분수 입력의 경우에는 아무런차이가 없습니다.무한, NaN 또는 영분수 입력의 경우에는 아무런 차이가 없습니다.유한한 수 결과가 주어졌을 때, IEEE 754 표준은 그 결과가 실수 분할의 결과일 것을 요구합니다.f1/f2
, 나눗셈에서 사용하는 유형으로 반올림합니다.
만일 그것이 a로 행해진다면.float
가장 가까운 나눗셈float
정확한 결과로다음과 같이 하면 됩니다.double
나눗셈, 그것은 가장 가까울 것입니다.double
에 대한 과제를 위해 추가적인 반올림 단계와 함께.result
.
대부분의 입력에서 두 개는 동일한 답변을 제공합니다.다음에서 수행되었기 때문에 분할에서 발생하지 않은 오버플로 또는 언더플로double
그 대신에 전환될 겁니다
단순 변환의 경우, 답이 두 개 사이의 절반에 매우 가깝다면float
두 반올림 단계에서 잘못된 값을 선택할 수 있습니다.float
. 저는 이것이 분할 결과에도 적용될 수 있다고 생각했었습니다.그러나 파스칼 쿠오크는 이 답에 대한 논평에서 피에르 루의 매우 흥미로운 논문인 기본 산술 연산의 무해한 이중 반올림에 주목하여 이중 반올림이 분할을 포함한 여러 연산에 무해하다는 증거를 주장했습니다.제가 이 답변을 시작할 때 제가 했던 가정에 내포된 조건에서.
개별 부동 소수점 덧셈, 뺄셈, 곱셈, 나눗셈의 결과가 즉시 a에 저장되는 경우float
, 를 사용하여 정확도를 향상시키는 것은 없을 것입니다.double
중간 값의 경우.그러나 연산이 함께 체인으로 연결된 경우에는 일관성 있게 사용할 경우 고정밀 중간 유형을 사용함으로써 정확도가 향상되는 경우가 많습니다.1986년경 터보 파스칼의 코드는 다음과 같습니다.
Function TriangleArea(A: Single, B:Single, C:Single): Single
Begin
Var S: Extended; (* S stands for Semi-perimeter *)
S := (A+B+C) * 0.5;
TriangleArea := Sqrt((S-A)*(S-B)*(S-C)*S)
End;
는 부동 소수점 연산의 모든 피연산자를 확장형(80비트 부동 소수점)으로 확장한 다음 해당 유형의 변수로 저장할 때 단일 또는 이중 정밀도로 다시 변환합니다.수치 처리를 위한 아주 좋은 의미론입니다.그 지역의 터보 C는 비슷하게 행동했지만, 오히려 중간 결과를 가질 수 있는 어떤 숫자 유형도 제공하는 데 도움이 되지 않았습니다; 언어가 중간 결과를 가질 수 있는 변수 유형을 제공하는 데 실패함으로써 사람들은 더 고정밀 중간 결과 유형의 개념을 부당하게 비판하게 되었습니다.언어들이 그것을 제대로 지원하지 못했다는 것이 진짜 문제였을 때.
어쨌든 위의 방법을 C#와 같은 현대 언어로 쓴다면:
public static float triangleArea(float a, float b, float c)
{
double s = (a + b + c) * 0.5;
return (double)(Math.Sqrt((s - a) * (s - b) * (s - c) * s));
}
만약 컴파일러가 우연히 추가의 피연산자들을 촉진한다면 그 코드는 잘 작동할 것입니다.double
계산을 수행하기 전에, 하지만 그것은 할 수도 있고 하지 않을 수도 있습니다.컴파일러가 다음과 같이 계산을 수행할 경우float
, 정밀도는 끔찍할 수도 있습니다.위의 공식을 사용하여 16777215의 긴 변과 4의 짧은 변을 갖는 이등변 삼각형의 넓이를 계산할 때, 열을 올리는 것은 수학을 수행하는 동안 3.355443E+7의 정확한 결과를 산출할 것입니다.float
피연산자의 순서에 따라 5.033165E+7 [50% 이상 너무 큼] 또는 16777214.0 [50% 이상 너무 작음]을 산출합니다.
위와 같은 코드는 일부 환경에서는 완벽하게 작동하지만 다른 환경에서는 완전히 잘못된 결과를 초래하지만 컴파일러는 일반적으로 상황에 대해 경고를 하지 않습니다.
개별적인 작업을 수행하지만float
즉시 저장될 것입니다.float
유형과 동일하게 정확하게 수행될 수 있습니다.float
그들이 활자라고 할 수 있는 한.double
, 열심히 피연산자를 홍보하는 것은 종종 운영이 결합될 때 상당한 도움이 될 것입니다.경우에 따라 재정렬 작업은 승격 손실로 인한 문제를 방지할 수 있습니다(예: 위 수식은 5개의 덧셈, 4개의 곱셈 및 제곱근을 사용하며 공식을 다음과 같이 다시 씁니다).
Math.Sqrt((a+b+c)*(b-a+c)*(a-b+c)*(a-c+b))*0.25
는 추가 수를 8개로 늘렸지만, 단일 정밀도로 수행하더라도 올바르게 작동합니다.
"플로트 분할 시 더블 캐스팅 및 백 캐스팅 시 정확도 향상?"
결과는 게시된 두 가지 방법 외에 다른 요인에 따라 달라집니다.
C를 평가할 수 있습니다.float
다음에 따라 다른 수준에서 작업이 발생합니다.FLT_EVAL_METHOD
표이 1 두 (아래 표 참조) 현재 설정이 1 또는 2인 경우 OP에 의해 게시된 두 가지 메소드는 동일한 답변을 제공합니다.
다른 코드와 컴파일러 최적화 레벨에 따라, 몫(quotient)result
OP의 경우 다음 계산에서 보다 정밀하게 사용할 수 있습니다.
때문에, 에 a.float
극단적으로 인해 0.0(총 정밀도 손실이 발생한 결과)으로 넘치거나 0.0이 되는 분할float
다음 계산에 최적화된 경우, 실제로 몫이 다음과 같이 이월됨에 따라 초과/미만 흐름이 발생하지 않을 수 있습니다.double
.
계수를 강제로 A가 되도록 하는 것.float
잠재적인 최적화 가운데에서 미래의 계산을 위해 코드는 종종 다음을 사용합니다.volatile
volatile float result = f1 / f2;
C는 수학 연산의 정밀도를 명시하지 않지만 IEEE 754와 같은 표준의 일반적인 적용은 이진수 32 나누기와 같은 단일 연산이 표현 가능한 가장 가까운 답을 도출할 것입니다.분할이 더 넓은 형식으로 발생하는 것은 다음과 같이.double
아니면long double
, 그 다음에 더 넓은 몫의 전환은float
드문 경우에 직접적인 답변과 다른 답변을 얻을 수 있는 또 다른 라운드 단계를 경험합니다.float/float
.
FLT_EVAL_METHOD
-1
확정할 수 없는
0
형식의 범위와 정밀도에 맞추어 모든 연산과 상수를 평가합니다.
1
유형의 연산 및 상수 평가float
그리고.double
범위와 정밀도로double
유형, 평가long double
범위 및 정밀도에 대한 연산 및 상수long double
자;
2
모든 연산과 상수를 범위와 정밀도에 맞추어 평가합니다.long double
형.
실무 지침:
사용하다float
대double
필요할 때 공간을 절약할 수 있습니다.float
일반적으로 더 좁고, 거의 같지 않습니다.double
) 정밀도가 중요한 경우 사용double
(또는long double
).
으로.float
대double
플랫폼의 기본 운영 방식이 모두 작동할 수도 있고 작동하지 않을 수도 있기 때문에 속도를 향상시키는 것은double
도 있고, 더 수도 있습니다 - 할 수 있습니다 프로필을 확인하는 것이 더 빠를 수도 있고, 동일할 수도 있고 느릴 수도 있습니다.C의 대부분은 원래 다음과 같이 설계되었습니다.double
레벨 FP만 수행되었기 때문에double
로/ 로부터float
회심의 회심나중에 C는 다음과 같은 기능을 추가했습니다.sinf()
더 빠르고 직접적인 방법으로float
작전.따라서 컴파일러/플랫폼이 현대적일수록float
더 빠를 겁니다.다시 한 번: 프로필을 통해 알아봅니다.
언급URL : https://stackoverflow.com/questions/28343772/is-there-any-accuracy-gain-when-casting-to-double-and-back-when-doing-float-divi
'it-source' 카테고리의 다른 글
AJAX 호출 데이터를 반환하는 자바스크립트 함수 (0) | 2023.10.23 |
---|---|
ASP.NET MVC 및 뷰 상태 (0) | 2023.10.23 |
안드로이드 버전과 코드 버전 번호를 변경하는 방법은? (0) | 2023.10.23 |
파이썬 셸에서 pyspark 가져오기 (0) | 2023.10.23 |
컴파일러는 무한 루프를 제거할 수 있습니까? (0) | 2023.10.23 |