cout을 사용하여 배정 밀도로 double 값을 인쇄하려면 어떻게합니까?


답변:


390

정밀도를 직접 설정 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;

46
왜 명시 적으로 사용하는 것이 fixed좋습니까? 함께 double h = 6.62606957e-34;, fixed저 제공 0.000000000000000하고 scientific출력 6.626069570000000e-34.
Arthur

36
값이 동일한 원래 값으로 반올림되도록 10 진수에서 이진 표현으로 다시 변환 할 때 2 개의 추가 숫자가 필요하므로 정밀도는 17 (또는 std :: numeric_limits <double> :: digits10 + 2)이어야합니다. 여기에 몇 가지 세부 사항 종이입니다 docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
마이크 피셔

8
정말 정답입니까? 수동으로 높은 숫자를 사용하면 대략 51 자리의 근사값을 인쇄 할 수 있지만 cout.precision(numeric_limits<double>::digits10 + 2);16 자리 만 얻을 수 있습니다.
Assimilater

6
@MikeFisher가 인용 한 논문에서 17 자리 숫자를 언급 한 사람들은 Theorem 15에 해당합니다.
Emile Cormier

15
@MikeFisher 당신이 옳습니다. C ++ 11max_digits10 은 같은 것을 나타 내기 위해 소개 합니다. 이것을 반영하도록 답변을 수정했습니다.
legends2k

70

사용 std::setprecision:

std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;

2
어떤 종류의 MAX_PRECISION 매크로 또는 열거 형 또는 std :: setPrecision에 전달할 수있는 것이 있습니까?
Jason Punyon

2
std :: setprecision (15) double (ok 또는 16), log_10 (2 ** 53) ~ = 15.9
user7116

14
std :: setprecision (std :: numeric_limits <double> :: digits10)
Éric Malenfant 님이

6
해야 std::setprecision (17)두 배를 들어, @ 빌 도마뱀의 답변에 대한 의견을 참조하십시오.
Alec Jacobson

9
std :: setprecision이 작동하려면 #include <iomanip>이 포함되어야합니다.
user2262504

24

다음은 내가 사용하는 것입니다.

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을 참조하십시오
.


12
이 헤더는 다음을 사용하는 데 필요합니다 std::setprecision(). #include <iomanip>
Martin Berger

그것은해야한다 std::numeric_limits<double>대신numberic_limits<double>
niklasfi

2
왜 추가하는 방법은 무엇 1으로 std::numeric_limits<double>::digits10?
Alessandro Jacopson

5
@LokiAstari max_digits10대신 C + 11을 사용할 수 있습니다 . 참조 .
legends2k

1
@AlecJacobson 그것은 오히려해야 max_digits10하지 어떤 임의의, digits10+2. 그렇지 않으면,의 경우 float, long double, boost::multiprecision::float128당신이 필요로하는 것이 있기 때문에이 실패합니다 +3대신 +2.
Ruslan

14

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


부스트 문서에 "std :: numeric_limits의 해당 전문화가있는 숫자의 경우 현재 버전은 이제 일치하는 정밀도를 선택합니다"라고 말합니다. 이것은 최대 정밀도를 얻는 가장 쉬운 방법처럼 보입니다. ( boost.org/doc/libs/1_58_0/doc/html/boost_lexical_cast/… )
JDiMatteo가 ​​15:15

11

완전 정밀도로, 나는 의도 된 값에 가장 가까운 근사치를 표시하기에 충분한 정밀도를 가정하지만, 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;

10

완전 정밀도로 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>

4
이것은 100.0000000000005정확히로 표현되지 않기 때문에 발생 합니다 double. (필수처럼 보일 수도 있지만 정규화 되기 때문에 그렇지 않습니다 . 즉, 이진 표현입니다). 이것을 보려면 다음을 시도하십시오 100.0000000000005 - 100.. 우리는 얻는다 4.973799150320701e-13.
Evgeni Sergeev

9

doublecout을 사용하여 완전 정밀도 로 값을 인쇄하려면 어떻게합니까 ?

정밀도 사용 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) 정밀도 중 하나만 처리합니다. 너무 정확한 답변이 필요한 값을 제공하지 않습니다. 따라서 이것은 오래된 질문에 대한 답변입니다.

  1. 어떤 기지?

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

  1. 그렇지 않으면 : fixed또는 scientific?

A double고정 소수점이 아닌 부동 소수점 유형 입니다.

작은 것만 인쇄 할 수 없으므로 사용 하지 마십시오 . 큰 경우 많은 숫자, 아마도 수백 개의 의심스러운 정보를 인쇄 합니다.std::fixeddouble0.000...000double

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

  1. 얼마나 많은 정밀도 (총 자릿수)?

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

비슷한 C 질문


좋은 대답입니다! 그러나 몇 가지주의 사항 : precision()과학 모드의 소수점 이하 자릿수를 설정하는 것이 맞습니다 . 을 지정하지 않으면 scientific지수를 제외한 총 자릿수를 설정합니다. 숫자 값에 따라 여전히 과학적 결과가 나올 수 있지만 지정한 것보다 적은 숫자를 얻을 수도 있습니다. 예 :에 cout.precision(3); cout << 1.7976931348623158e+308; // "1.8e+308"대한 결과 printf가 다를 수 있습니다. 혼란스러운 것들을 알고 있어야합니다.
Simpleton

후손을 위해, printf를 사용하여 과학 모드에서 모든 이중 숫자의 정확한 문자열 표현을 보장하는 데 필요한 버퍼 길이는 다음과 같습니다 char buf[DBL_DECIMAL_DIG + 3 + 5]; sprintf(buf, "%.*g", DBL_DECIMAL_DIG, d);. 추가 문자는 부호, 소수점, 후행 0, e [+ |-], 지수의 3 자리 ( DBL_MAX_10_EXP = 308). 따라서 필요한 문자의 총 수는 25입니다
바보

첫 번째 주석을 편집 할 수 없으므로 여기로 다시갑니다. 과학 모드의 또 다른 문제는 지수 출력을 사용하지 않기로 결정하고 부동 소수점 출력을 전혀 사용하지 않기로 결정할 수도 있다는 것입니다. 즉, 1.0을 "1"로 출력하므로 직렬화 / 직렬화 컨텍스트에서 문제가 될 수 있습니다. "% #. * g"를 사용하여 소수점을 강제로 출력 할 수 있지만, 이것은 후행 0을 추가한다는 단점이 있습니다. #이 없으면 0입니다.
Simpleton

3
printf("%.12f", M_PI);

% .12f는 12 자리의 정밀도로 부동 소수점을 의미합니다.


11
이것은 "cout 사용"이 아닙니다.
Johnsyweb

2
12 자리 숫자는 "정확도"가 아닙니다
Roland Illig

0

가장 이식성있는 ...

#include <limits>

using std::numeric_limits;

    ...
    cout.precision(numeric_limits<double>::digits10 + 1);
    cout << d;

16
궁금합니다. 왜 "+1"입니까?
Éric Malenfant

0

ostream :: precision (int) 사용

cout.precision( numeric_limits<double>::digits10 + 1);
cout << M_PI << ", " << M_E << endl;

생산할 것이다

3.141592653589793, 2.718281828459045

왜 "+1"이라고 말해야하는지 모르겠습니다. 단, 추가 자리수는 맞습니다.


3
numeric_limits <unsigned char> :: digits10은 2와 같습니다. 두 개의 숫자 0..99를 포함 할 수 있으므로 10..99입니다. 또한 255 ..를 포함 할 수 있지만 256, 257 ... 300 등은 포함 할 수 없습니다. 이것이 numeric10이 3이 아닌 이유입니다! "+1"이 이런 것을 극복하기 위해 추가되었다고 생각합니다.
Dmitriy Yurchenko

0

점 다음에 소수점 이하 두 자리까지의 값이 표시됩니다.

#include <iostream>
#include <iomanip>

double d = 2.0;
int n = 2;
cout << fixed << setprecison(n) << d;

여기를 참조하십시오 : 고정 소수점 표기법

std :: 고정

고정 부동 소수점 표기법 사용 str 스트림에 대한 floatfield 형식 플래그를 fixed로 설정합니다.

floatfield가 fixed로 설정되면 부동 소수점 값은 고정 소수점 표기법을 사용하여 기록됩니다. 값은 정밀도 필드 (정밀도)에 의해 지정된 소수 부분과 지수 부분없이 정확하게 숫자로 표시됩니다.

std :: setprecision

소수 자릿수 설정 출력 연산에서 부동 소수점 값의 형식을 지정하는 데 사용할 소수 자릿수를 설정합니다.

부동 소수점을 표현하기위한 IEEE 표준에 익숙하다면 표준의 범위를 벗어난 완전 정밀도로 부동 소수점을 표시하는 것이 불가능하다는 것을 알고 있을 것입니다. 실제 가치의 반올림

먼저 값이 범위 내에 있는지 확인한 다음 예인 경우 다음을 사용하십시오.

cout << defaultfloat << d ;

std :: defaultfloat

기본 부동 소수점 표기법 사용 str 스트림에 대한 floatfield 형식 플래그를 defaultfloat로 설정합니다.

floatfield가 defaultfloat로 설정된 경우 부동 소수점 값은 기본 표기법을 사용하여 기록됩니다. 표현은 스트림의 소수점 정밀도 (정밀도)까지 필요한만큼 많은 숫자를 사용하여 소수점 앞뒤의 숫자를 세고 (있는 경우) ).

또한의 기본 동작 cout이므로 명시 적으로 사용하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.