그래서 나는 나의 마지막 질문에 대한 답을 얻었습니다 (왜 그런 생각을하지 않았는지 모르겠습니다). 나는 인쇄 된 double
사용 cout
나는 그것을 기대하지 않은 때 GOT가 반올림. 완전 정밀도로 cout
인쇄하려면 어떻게 double
해야합니까?
그래서 나는 나의 마지막 질문에 대한 답을 얻었습니다 (왜 그런 생각을하지 않았는지 모르겠습니다). 나는 인쇄 된 double
사용 cout
나는 그것을 기대하지 않은 때 GOT가 반올림. 완전 정밀도로 cout
인쇄하려면 어떻게 double
해야합니까?
답변:
정밀도를 직접 설정 std::cout
하고 std::fixed
형식 지정자를 사용할 수 있습니다 .
double d = 3.14159265358979;
cout.precision(17);
cout << "Pi: " << fixed << d << endl;
#include <limits>
float 또는 double의 최대 정밀도를 얻을 수 있습니다 .
#include <limits>
typedef std::numeric_limits< double > dbl;
double d = 3.14159265358979;
cout.precision(dbl::max_digits10);
cout << "Pi: " << d << endl;
cout.precision(numeric_limits<double>::digits10 + 2);
16 자리 만 얻을 수 있습니다.
max_digits10
은 같은 것을 나타 내기 위해 소개 합니다. 이것을 반영하도록 답변을 수정했습니다.
std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;
std::setprecision (17)
두 배를 들어, @ 빌 도마뱀의 답변에 대한 의견을 참조하십시오.
다음은 내가 사용하는 것입니다.
std::cout << std::setprecision (std::numeric_limits<double>::digits10 + 1)
<< 3.14159265358979
<< std::endl;
기본적으로 limits 패키지에는 모든 빌드 유형에 대한 특성이 있습니다.
부동 소수점 숫자 (float / double / long double)의 특성 중 하나는 numeric10 속성입니다. 이것은 밑 10의 부동 소수점 숫자의 정확성을 정의합니다 (정확한 용어를 잊어 버렸습니다).
다른 속성에 대한 자세한 내용은 http://www.cplusplus.com/reference/std/limits/numeric_limits.html을 참조하십시오
.
std::setprecision()
. #include <iomanip>
std::numeric_limits<double>
대신numberic_limits<double>
1
으로 std::numeric_limits<double>::digits10
?
max_digits10
하지 어떤 임의의, digits10+2
. 그렇지 않으면,의 경우 float
, long double
, boost::multiprecision::float128
당신이 필요로하는 것이 있기 때문에이 실패합니다 +3
대신 +2
.
iostreams 방식은 어색합니다. 나는 boost::lexical_cast
그것이 나에게 올바른 정밀도를 계산하기 때문에 사용하는 것을 선호합니다 . 그리고 그것은 또한 빠릅니다 .
#include <string>
#include <boost/lexical_cast.hpp>
using boost::lexical_cast;
using std::string;
double d = 3.14159265358979;
cout << "Pi: " << lexical_cast<string>(d) << endl;
산출:
파이 : 3.14159265358979
완전 정밀도로, 나는 의도 된 값에 가장 가까운 근사치를 표시하기에 충분한 정밀도를 가정하지만, double
밑이 2를 사용하여 저장되고 밑이 2가 1.1
정확하게 사소한 것을 나타낼 수 없다는 것이 지적되어야합니다 . 실제 배정도의 완전 정밀도 를 얻는 유일한 방법은 (NO ROUND OFF ERROR 포함) 이진 비트 (또는 16 진 nybbles)를 인쇄하는 것입니다. 이를 수행하는 한 가지 방법은 double
에 a를 쓴 union
다음 비트의 정수 값을 인쇄하는 것입니다.
union {
double d;
uint64_t u64;
} x;
x.d = 1.1;
std::cout << std::hex << x.u64;
이것은 당신에게 double의 100 % 정확한 정밀도를 줄 것입니다 ... 그리고 인간은 IEEE double 형식을 읽을 수 없기 때문에 완전히 읽을 수 없습니다! Wikipedia 에는 이진 비트를 해석하는 방법에 대한 훌륭한 글이 있습니다.
최신 C ++에서는 할 수 있습니다
std::cout << std::hexfloat << 1.1;
완전 정밀도로 double을 표시하는 방법은 다음과 같습니다.
double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::setprecision(precision) << d << std::endl;
다음이 표시됩니다.
100.0000000000005
max_digits10은 고유 한 모든 이중 값을 고유하게 나타내는 데 필요한 자릿수입니다. max_digits10은 소수점 전후 자릿수를 나타냅니다.
std :: fixed와 함께 set_precision (max_digits10)을 사용하지 마십시오.
고정 표기법에서 set_precision () 은 소수점 뒤에 만 자릿수를 설정합니다 . max_digits10이 자리의 수를 나타냅니다 이것은 잘못된 이전 과 이후에 소수점.
double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::fixed << std::setprecision(precision) << d << std::endl;
잘못된 결과가 표시됩니다.
100.00000000000049738
참고 : 헤더 파일이 필요합니다
#include <iomanip>
#include <limits>
100.0000000000005
정확히로 표현되지 않기 때문에 발생 합니다 double
. (필수처럼 보일 수도 있지만 정규화 되기 때문에 그렇지 않습니다 . 즉, 이진 표현입니다). 이것을 보려면 다음을 시도하십시오 100.0000000000005 - 100
.. 우리는 얻는다 4.973799150320701e-13
.
double
cout을 사용하여 완전 정밀도 로 값을 인쇄하려면 어떻게합니까 ?
정밀도 사용 hexfloat
또는
사용 scientific
및 설정
std::cout.precision(std::numeric_limits<double>::max_digits10 - 1);
std::cout << std::scientific << 1.0/7.0 << '\n';
// C++11 Typical output
1.4285714285714285e-01
답변이 너무 많으면 1) 기본 2) 고정 / 과학 레이아웃 또는 3) 정밀도 중 하나만 처리합니다. 너무 정확한 답변이 필요한 값을 제공하지 않습니다. 따라서 이것은 오래된 질문에 대한 답변입니다.
A double
는 확실히 base 2를 사용하여 인코딩됩니다. C ++ 11을 사용한 직접적인 접근 방식은을 사용하여 인쇄하는 것 std::hexfloat
입니다.
10 진이 아닌 출력이 허용되면 완료됩니다.
std::cout << "hexfloat: " << std::hexfloat << exp (-100) << '\n';
std::cout << "hexfloat: " << std::hexfloat << exp (+100) << '\n';
// output
hexfloat: 0x1.a8c1f14e2af5dp-145
hexfloat: 0x1.3494a9b171bf5p+144
fixed
또는 scientific
?A double
는 고정 소수점이 아닌 부동 소수점 유형 입니다.
작은 것만 인쇄 할 수 없으므로 사용 하지 마십시오 . 큰 경우 많은 숫자, 아마도 수백 개의 의심스러운 정보를 인쇄 합니다.std::fixed
double
0.000...000
double
std::cout << "std::fixed: " << std::fixed << exp (-100) << '\n';
std::cout << "std::fixed: " << std::fixed << exp (+100) << '\n';
// output
std::fixed: 0.000000
std::fixed: 26881171418161356094253400435962903554686976.000000
완전 정밀도로 인쇄하려면 먼저 std::scientific
"과학 표기법으로 부동 소수점 값을 작성합니다"를 사용하십시오. 소수점 이하의 기본값 인 6 자리 (불충분 한 금액)는 다음 포인트에서 처리됩니다.
std::cout << "std::scientific: " << std::scientific << exp (-100) << '\n';
std::cout << "std::scientific: " << std::scientific << exp (+100) << '\n';
// output
std::scientific: 3.720076e-44
std::scientific: 2.688117e+43
ㅏ double
이진베이스 2 인코딩이 종종 53 비트 (2)의 각종 능력과 동일한 정밀도를 사용하여 인코딩.
[1.0 ... 2.0) 2 53 가지가 double
있고,
[2.0 ... 4.0) 2 53 가지가 double
있고,
[4.0 ... 8.0) 2 53 가지가 double
있고,
[8.0 ... 10.0) 2 /가있다 8 * 2 53 가지double
.
그러나 코드가 N
유효 숫자 로 10 진수로 인쇄되는 경우 조합 수 [1.0 ... 10.0)는 9/10 * 10 N입니다. 입니다.
어떤 N
(정밀)을 선택 하든지 double
, 십진 텍스트 사이에는 일대일 매핑이 없습니다 . 고정 N
을 선택하면 때로는 특정 double
값에 필요한 것보다 약간 많거나 적을 수 있습니다 . 너무 적 a)
거나 ( 아래) 너무 많거나 ( 아래) 오류가 발생할 수 b)
있습니다.
3 후보 N
:
a) text-text에서 N
변환 할 때 so를 사용하여 double
모두 같은 텍스트에 도착합니다 double
.
std::cout << dbl::digits10 << '\n';
// Typical output
15
b)는을 사용하여 N
변환 할 때 너무 double
-text- double
우리가 같은 도착 double
모든 double
.
// C++11
std::cout << dbl::max_digits10 << '\n';
// Typical output
17
때 max_digits10
사용할 수 없습니다, 참고로 인해베이스 2베이스 (10) 속성 것을 digits10 + 2 <= max_digits10 <= digits10 + 3
, 우리가 사용할 수 있습니다digits10 + 3
충분한 진수를 보장하기 위해 인쇄됩니다.
c) N
값에 따라 다른를 사용하십시오 .
코드는 최소한의 텍스트 (표시하고자 할 때 유용 할 수 있습니다 N == 1
) 또는 정확한 의 값 double
( N == 1000-ish
의 경우를 denorm_min
). 그러나 이것이 "작업"이고 OP의 목표가 아닐 가능성이 있기 때문에 제외 될 것입니다.
일반적으로 b) " double
전체 정밀도 로 값을 인쇄"하는 데 사용됩니다 . 일부 응용 프로그램은 정보를 너무 많이 제공하지 않으면 a) 오류를 선호 할 수 있습니다.
함께 .scientific
, .precision()
그래서 세트 자릿수, 소수점 후 인쇄 1 + .precision()
숫자가 인쇄된다. 코드에는 max_digits10
총 자릿수 .precision()
가 필요 하므로 로 호출됩니다 max_digits10 - 1
.
typedef std::numeric_limits< double > dbl;
std::cout.precision(dbl::max_digits10 - 1);
std::cout << std::scientific << exp (-100) << '\n';
std::cout << std::scientific << exp (+100) << '\n';
// Typical output
3.7200759760208361e-44
2.6881171418161356e+43
//1234567890123456 17 total digits
precision()
과학 모드의 소수점 이하 자릿수를 설정하는 것이 맞습니다 . 을 지정하지 않으면 scientific
지수를 제외한 총 자릿수를 설정합니다. 숫자 값에 따라 여전히 과학적 결과가 나올 수 있지만 지정한 것보다 적은 숫자를 얻을 수도 있습니다. 예 :에 cout.precision(3); cout << 1.7976931348623158e+308; // "1.8e+308"
대한 결과 printf
가 다를 수 있습니다. 혼란스러운 것들을 알고 있어야합니다.
char buf[DBL_DECIMAL_DIG + 3 + 5]; sprintf(buf, "%.*g", DBL_DECIMAL_DIG, d);
. 추가 문자는 부호, 소수점, 후행 0, e [+ |-], 지수의 3 자리 ( DBL_MAX_10_EXP = 308). 따라서 필요한 문자의 총 수는 25입니다
printf("%.12f", M_PI);
% .12f는 12 자리의 정밀도로 부동 소수점을 의미합니다.
가장 이식성있는 ...
#include <limits>
using std::numeric_limits;
...
cout.precision(numeric_limits<double>::digits10 + 1);
cout << d;
ostream :: precision (int) 사용
cout.precision( numeric_limits<double>::digits10 + 1);
cout << M_PI << ", " << M_E << endl;
생산할 것이다
3.141592653589793, 2.718281828459045
왜 "+1"이라고 말해야하는지 모르겠습니다. 단, 추가 자리수는 맞습니다.
점 다음에 소수점 이하 두 자리까지의 값이 표시됩니다.
#include <iostream>
#include <iomanip>
double d = 2.0;
int n = 2;
cout << fixed << setprecison(n) << d;
여기를 참조하십시오 : 고정 소수점 표기법
고정 부동 소수점 표기법 사용 str 스트림에 대한 floatfield 형식 플래그를 fixed로 설정합니다.
floatfield가 fixed로 설정되면 부동 소수점 값은 고정 소수점 표기법을 사용하여 기록됩니다. 값은 정밀도 필드 (정밀도)에 의해 지정된 소수 부분과 지수 부분없이 정확하게 숫자로 표시됩니다.
소수 자릿수 설정 출력 연산에서 부동 소수점 값의 형식을 지정하는 데 사용할 소수 자릿수를 설정합니다.
부동 소수점을 표현하기위한 IEEE 표준에 익숙하다면 표준의 범위를 벗어난 완전 정밀도로 부동 소수점을 표시하는 것이 불가능하다는 것을 알고 있을 것입니다. 실제 가치의 반올림
먼저 값이 범위 내에 있는지 확인한 다음 예인 경우 다음을 사용하십시오.
cout << defaultfloat << d ;
기본 부동 소수점 표기법 사용 str 스트림에 대한 floatfield 형식 플래그를 defaultfloat로 설정합니다.
floatfield가 defaultfloat로 설정된 경우 부동 소수점 값은 기본 표기법을 사용하여 기록됩니다. 표현은 스트림의 소수점 정밀도 (정밀도)까지 필요한만큼 많은 숫자를 사용하여 소수점 앞뒤의 숫자를 세고 (있는 경우) ).
또한의 기본 동작 cout
이므로 명시 적으로 사용하지 않습니다.
fixed
좋습니까? 함께double h = 6.62606957e-34;
,fixed
저 제공0.000000000000000
하고scientific
출력6.626069570000000e-34
.