긴 이중 출력의 정밀도는 정확하지 않습니다. 무엇이 잘못되었을 수 있습니까?
-
22-08-2019 - |
문제
나는있다 long double
내가 const 또는 const로 설정하고 있다고 상수. A의 정밀도보다 길다 (40 자리) long double
내 테스트 워크 스테이션 (19 자리)에서.
인쇄하면 더 이상 정밀도 19 자리가 아니라 16 숫자로 표시됩니다.
내가 테스트하는 코드는 다음과 같습니다.
#include <iostream>
#include <iomanip>
#include <limits>
#include <cstdio>
int main ()
{
const long double constLog2 = 0.6931471805599453094172321214581765680755;
long double log2 = 0.6931471805599453094172321214581765680755;
std::cout << std::numeric_limits<long double>::digits10 + 1 << std::endl;
std::cout << "const via cout: " << std::setprecision(19) << constLog2 << std::endl;
std::cout << "non-const via cout: " << std::setprecision(19) << log2 << std::endl;
std::fprintf(stdout, "const via printf: %.19Lf\n", constLog2);
std::fprintf(stdout, "non-const via printf: %.19Lf\n", log2);
return 0;
}
엮다:
$ g++ -Wall precisionTest.cpp
산출:
$ ./a.out
19
const via cout: 0.6931471805599452862
non-const via cout: 0.6931471805599452862
const via printf: 0.6931471805599452862
non-const via printf: 0.6931471805599452862
나는 기대할 것이다 0.6931471805599453094
그러나 대신 얻습니다 0.6931471805599452862
.
19 자리 숫자의 정밀도가 16 자리로 절단되는 이유가 있습니까?
여기 내 환경이 있습니다.
$ gcc --version
i686-apple-darwin9-g++-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5490)
다른 버전의 GCC와 같은 문제가 있습니다.
$ gcc --version
g++ (GCC) 3.4.6 20060404 (Red Hat 3.4.6-10)
나는 NTL이나 다른 라이브러리를 살펴볼 수 있지만 이것을 일으키는 원인이 궁금합니다. 당신의 통찰에 감사드립니다.
해결책
나는이 출력을 얻는다 :
19
const via cout: 0.6931471805599453094
non-const via cout: 0.6931471805599453094
const via printf: 0.6931471805599453094
non-const via printf: 0.6931471805599453094
그러나 나는 더블 리터럴 대신 긴 이중 리터럴을 사용하고 있습니다.
const long double constLog2 = 0.6931471805599453094172321214581765680755L;
long double log2 = 0.6931471805599453094172321214581765680755L;
다른 팁
하드웨어 플랫폼 및 컴파일 옵션과 관련된 몇 가지 미묘한 문제가 있습니다.
- https://www.amazon.com/exec/obidos/asin/0954161793/networktheory-20
- 3.17.3 인텔 386 및 AMD X86-64 옵션 (GCC-4.0.1) (보관 된 개발자 .apple.com 문서)
- 3.17.12 Intel 386 및 AMD X86-64 옵션 (GCC-4.0.1) (gcc.gnu.org 문서)
이`-m '옵션은 i386 및 x86-64 컴퓨터 제품군에 대해 정의됩니다.
-M96 비트-더우블
-M128 비트-더우블
이 스위치는 긴 이중 유형의 크기를 제어합니다. i386 애플리케이션 바이너리 인터페이스는 크기를 96 비트로 지정하므로 -M96 비트-더우블은 32 비트 모드의 기본값입니다. 현대 아키텍처 (Pentium and Newer)는 8 또는 16 바이트 경계에 정렬되는 것을 선호합니다. ABI를 준수하는 배열 또는 구조에서는 불가능합니다. 따라서 -m128 비트-더우블을 지정하면 긴 더블을 추가로 32 비트 0으로 패딩하여 긴 더블을 16 바이트 경계에 정렬합니다.
X86-64 컴파일러에서 -M128 비트-더우블 더블은 ABI가 16 바이트 경계에서 긴 더블을 정렬해야한다고 지정함에 따라 기본 선택입니다.
이 옵션 중 어느 것도 X87 표준 80 비트에 대한 추가 정밀도를 제공하지 않습니다.
경고 : 대상 ABI의 기본값을 무시하면 긴 이중 변수가 포함 된 구조 및 배열이 크기가 변경되며 기능 호출 컨벤션이 긴 이중을 차지하는 기능이 수정됩니다. 따라서 해당 스위치없이 컴파일 된 코드의 배열 또는 구조와 이진 호환되지 않습니다.