float와 double의 차이점은 무엇입니까?


420

배정 밀도와 단 정밀도의 차이점에 대해 읽었습니다. 그러나 대부분의 경우, float그리고 double하나를 사용하여 즉, 상호 교환 보이거나 다른 하나는 결과에 영향을 미칠 것 같지 않습니다. 이것이 사실입니까? 수레와 복식은 언제 교환 할 수 있습니까? 그들 사이의 차이점은 무엇입니까?

답변:


521

큰 차이.

이름에서 알 수 있듯이 a double의 정밀도는 [1] 의 2 배 입니다. 일반적으로 a 는 십진수 15 자리이며, 7은 7입니다.floatdoublefloat

자릿수 계산 방법은 다음과 같습니다.

double52 가수 비트 + 1 숨겨진 비트 : log (2 53 ÷÷ log (10) = 15.95 자리

float23 개의 가수 비트 + 1 개의 숨겨진 비트 : log (2 24 ÷÷ log (10) = 7.22 자리

이 정밀 손실로 인해 반복 계산을 수행 할 때 더 큰 잘림 오류가 누적 될 수 있습니다.

float a = 1.f / 81;
float b = 0;
for (int i = 0; i < 729; ++ i)
    b += a;
printf("%.7g\n", b); // prints 9.000023

동안

double a = 1.0 / 81;
double b = 0;
for (int i = 0; i < 729; ++ i)
    b += a;
printf("%.15g\n", b); // prints 8.99999999999996

또한 float의 최대 값은 약 3e38이지만 double은 약 1.7e308이므로를 사용 float하면 "인피니티"(예 : 특수 부동 소수점 숫자)를 double간단한 것보다 훨씬 쉽게 맞출 수 있습니다 (예 : 계승 60 계산).

테스트하는 동안 소수의 테스트 사례에 이러한 큰 숫자가 포함되어있을 수 있으며 플로트를 사용하면 프로그램이 실패 할 수 있습니다.


물론 때로는 double충분히 정확 하지도 않기 때문에 때때로 우리는 long double[1] (위의 예는 Mac에서 9.000000000000000066을 나타냄)을 갖지만 모든 부동 소수점 유형은 반올림 오류를습니다 . 따라서 정밀도가 매우 중요한 경우 (예 : 돈) 처리) int또는 분수 클래스 를 사용해야합니다 .


또한 +=오류가 빠르게 누적되므로 많은 부동 소수점 수를 합산 하는 데 사용하지 마십시오 . Python을 사용하는 경우을 사용하십시오 fsum. 그렇지 않으면 Kahan summation 알고리즘 을 구현하십시오 .


[1] : C 및 C ++ 표준은 float, double및 의 표현을 지정하지 않습니다 long double. 세 가지 모두 IEEE 배정 밀도로 구현 될 수 있습니다. 그럼에도 불구하고, 대부분의 아키텍처 (GCC, MSVC, 86, 64, ARM은) float 입니다 실제로 소수점 수 (binary32)를 부동 IEEE 단 정밀도하고 double 있다 IEEE 배정 밀도 부동 소수점 숫자 (binary64).


9
합계에 대한 일반적인 조언은 합산하기 전에 부동 소수점 숫자를 크기 (가장 작은 것부터)로 정렬하는 것입니다.
R .. GitHub 중지 지원 얼음

C / C ++ float 및 double은 거의 항상 IEEE single 및 double precision이지만 C / C ++ long double은 CPU, 컴파일러 및 OS에 따라 훨씬 다양합니다. 때로는 double과 동일하고 때로는 시스템 특정 확장 형식이거나 때로는 IEEE 쿼드 정밀도입니다.
plugwash

@ R..GitHubSTOPHELPINGICE : 왜? 설명해 주시겠습니까?
Inquisitive

@InQusitive : 예를 들어 값 2 ^ 24와 값 2의 2 ^ 24 반복으로 구성된 배열을 고려하십시오. 순서대로 합하면 2 ^ 24가됩니다. 반전하면 2 ^ 25가 생성됩니다. 물론 하나의 누산기로 모든 주문이 치명적으로 잘못되었지만 예를 들어 가장 작은 크기가 가장 좋은 예를 만들 수 있습니다 (예 : 2 ^ 25 반복 1). 더 잘하려면 어떤 종류의 나무가 필요합니다.
R .. GitHub 중지 지원 얼음

56

표준 C99 (ISO-IEC 9899 6.2.5 §10) 또는 C ++ 2003 (ISO-IEC 14882-2003 3.1.9 §8) 표준은 다음과 같습니다.

부동 소수점 유형 float에는 double, 및 , 세 가지가 있습니다 long double. 타입 double은 최소한 정밀도를 제공 float하고 타입 long double은 최소한 정밀도를 제공 double합니다. 유형의 값 세트는 유형의 값 세트의 float서브 세트입니다 double. 유형의 값 세트는 유형의 값 세트의 double서브 세트입니다 long double.

C ++ 표준은 다음을 추가합니다.

부동 소수점 유형의 값 표현은 구현 정의됩니다.

IEEE 부동 소수점 표준을 심도있게 다루는 모든 컴퓨터 과학자가 부동 소수점 산술에 대해 알아야 할 훌륭한 점을 살펴볼 것을 제안 합니다. 표현 세부 사항에 대해 배우고 크기와 정밀도 사이에 상충 관계가 있음을 알게됩니다. 부동 소수점 표현의 정밀도는 크기가 감소함에 따라 증가하므로 -1과 1 사이의 부동 소수점 숫자는 가장 정밀한 숫자입니다.


27

이차 방정식을 감안할 : X 2  - 4.0000000  X  + 3.9999999 = 0, 정확한 뿌리 10의 유효 숫자는, R 1  = 2.000316228 및 R 2  = 1.999683772.

floatand를 사용 double하여 테스트 프로그램을 작성할 수 있습니다.

#include <stdio.h>
#include <math.h>

void dbl_solve(double a, double b, double c)
{
    double d = b*b - 4.0*a*c;
    double sd = sqrt(d);
    double r1 = (-b + sd) / (2.0*a);
    double r2 = (-b - sd) / (2.0*a);
    printf("%.5f\t%.5f\n", r1, r2);
}

void flt_solve(float a, float b, float c)
{
    float d = b*b - 4.0f*a*c;
    float sd = sqrtf(d);
    float r1 = (-b + sd) / (2.0f*a);
    float r2 = (-b - sd) / (2.0f*a);
    printf("%.5f\t%.5f\n", r1, r2);
}   

int main(void)
{
    float fa = 1.0f;
    float fb = -4.0000000f;
    float fc = 3.9999999f;
    double da = 1.0;
    double db = -4.0000000;
    double dc = 3.9999999;
    flt_solve(fa, fb, fc);
    dbl_solve(da, db, dc);
    return 0;
}  

프로그램을 실행하면 다음이 제공됩니다.

2.00000 2.00000
2.00032 1.99968

숫자는 크지 않지만 여전히을 사용하여 취소 효과를 얻을 수 float있습니다.

(실제로 위의 방법은 단 정밀도 또는 배정 밀도 부동 소수점 숫자를 사용하여 2 차 방정식을 푸는 가장 좋은 방법은 아니지만 보다 안정적인 방법을 사용하더라도 답은 변하지 않습니다 .)


19
  • double은 64이고 single precision (float)은 32 비트입니다.
  • double은 더 큰 가수 (실수의 정수 비트)를 갖습니다.
  • 부정확 한 부분은 두 배로 작습니다.

12

부동 소수점 계산과 관련된 숫자의 크기는 가장 관련성이 없습니다. 수행되는 계산은 관련이 있습니다.

본질적으로 계산을 수행하고 결과가 비합리적인 숫자 또는 반복되는 10 진수 인 경우 해당 숫자가 사용중인 유한 크기 데이터 구조로 스쿼시되면 반올림 오류가 발생합니다. double은 float의 두 배 크기이므로 반올림 오류가 훨씬 작습니다.

테스트는 특히 이런 종류의 오류를 유발하는 숫자를 사용할 수 있으므로 코드에서 적절한 유형을 사용했는지 테스트했습니다.


9

32 비트 길이의 float 유형은 정밀도가 7 자리입니다. 매우 크거나 아주 작은 범위 (+/- 3.4 * 10 ^ 38 또는 * 10 ^ -38)의 값을 저장할 수 있지만 유효 숫자는 7 자리입니다.

64 비트 길이의 double 유형은 더 큰 범위 (* 10 ^ + /-308)와 15 자리 정밀도를 갖습니다.

long double 타입은 명목상 80 비트이지만 주어진 컴파일러 / OS 쌍은 정렬을 위해 12-16 바이트로 저장할 수 있습니다. long double에는 엄청나게 큰 지수가 있으며 19 자리의 정밀도를 가져야합니다. Microsoft는 무한한 지혜로 long double을 8 바이트로 제한하며 일반 double과 동일합니다.

일반적으로 부동 소수점 값 / 변수가 필요할 때 double 유형을 사용하십시오. 표현식에 사용 된 리터럴 부동 소수점 값은 기본적으로 더블로 처리되며 부동 소수점 값을 반환하는 대부분의 수학 함수는 더블을 반환합니다. 두 번만 사용하면 많은 두통과 타입 캐스팅을 줄일 수 있습니다.



9

방금 나를 알아 내고 실수로 플로트 정밀도의 좋은 예를 줄 수있는 오류가 발생했습니다.

#include <iostream>
#include <iomanip>

int main(){
  for(float t=0;t<1;t+=0.01){
     std::cout << std::fixed << std::setprecision(6) << t << std::endl;
  }
}

출력은

0.000000
0.010000
0.020000
0.030000
0.040000
0.050000
0.060000
0.070000
0.080000
0.090000
0.100000
0.110000
0.120000
0.130000
0.140000
0.150000
0.160000
0.170000
0.180000
0.190000
0.200000
0.210000
0.220000
0.230000
0.240000
0.250000
0.260000
0.270000
0.280000
0.290000
0.300000
0.310000
0.320000
0.330000
0.340000
0.350000
0.360000
0.370000
0.380000
0.390000
0.400000
0.410000
0.420000
0.430000
0.440000
0.450000
0.460000
0.470000
0.480000
0.490000
0.500000
0.510000
0.520000
0.530000
0.540000
0.550000
0.560000
0.570000
0.580000
0.590000
0.600000
0.610000
0.620000
0.630000
0.640000
0.650000
0.660000
0.670000
0.680000
0.690000
0.700000
0.710000
0.720000
0.730000
0.740000
0.750000
0.760000
0.770000
0.780000
0.790000
0.800000
0.810000
0.820000
0.830000
0.839999
0.849999
0.859999
0.869999
0.879999
0.889999
0.899999
0.909999
0.919999
0.929999
0.939999
0.949999
0.959999
0.969999
0.979999
0.989999
0.999999

0.83 이후에 볼 수 있듯이 정밀도는 크게 떨어집니다.

그러나 t이중으로 설정하면 이러한 문제가 발생하지 않습니다.

이 사소한 오류를 깨닫는 데 5 시간이 걸렸으며 이로 인해 프로그램이 손상되었습니다.


4
확실하게 : 문제의 해결책은 int를 바람직하게 사용하는 것이어야합니까? 100 번 반복하고 싶다면 double을 사용하는 대신 int로 계산해야합니다.
BlueTrin

8
여기서 사용 double하는 것은 좋은 해결책이 아닙니다. int부동 소수점 값을 얻기 위해 내부 곱셈을 계산하고 수행하는 데 사용 합니다.
Richard


3

부동 소수점 숫자를 사용할 때는 로컬 테스트가 서버 측에서 수행 된 테스트와 정확히 동일하다는 것을 신뢰할 수 없습니다. 환경과 컴파일러는 로컬 시스템과 최종 테스트가 실행되는 위치가 다를 수 있습니다. 일부 TopCoder 경쟁 에서이 문제를 여러 번 전에 보았습니다. 특히 두 개의 부동 소수점 숫자를 비교하려고하면 더욱 그렇습니다.


3

내장 비교 연산은 2 개의 숫자를 부동 소수점과 비교할 때와 다르므로 데이터 유형 (예 : float 또는 double)의 차이로 인해 다른 결과가 발생할 수 있습니다.


1

임베디드 프로세싱으로 작동한다면, 결국 기본 하드웨어 (예 : FPGA 또는 일부 특정 프로세서 / 마이크로 컨트롤러 모델)는 하드웨어에서 최적으로 플로트 (float)를 구현하는 반면, 더블은 소프트웨어 루틴을 사용합니다. 따라서 float의 정밀도가 요구 사항을 처리하기에 충분하면 프로그램은 float보다 double 배 빠른 속도로 몇 배 더 빠르게 실행됩니다. 다른 답변에서 언급했듯이 누적 오류에주의하십시오.


-1

int(정수) 와 달리 float소수점이 있으므로 a도 가능합니다 double. 그러나이 둘의 차이점은 a double가 a 보다 두 배 더 상세 float하다는 것입니다. 즉, 소수점 다음에 두 배의 숫자를 가질 수 있습니다.


4
그렇다는 의미는 아닙니다. 실제로 정수 십진수의 두 배를 의미하며 두 배 이상입니다. 소수와 정밀도의 관계는 선형이 아닙니다. 값에 따라 다릅니다. 예를 들어 0.5는 정확하지만 0.33333333333333333333은 그렇지 않습니다.
Lorne의 후작
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.