왜 float / double이 필요합니까?


29

나는 http://www.joelonsoftware.com/items/2011/06/27.html 을보고 있었고 Jon Skeet 농담에서 0.3이 아닌 0.3에 대해 웃었습니다. 나는 개인적으로 float / decimals / doubles에 문제가 없었지만 6502를 매우 일찍 배웠고 대부분의 프로그램에서 float가 필요하지 않았다는 것을 기억합니다. 내가 사용한 유일한 시간은 그래픽과 수학에서 정확하지 않은 숫자가 정확하고 출력이 화면에 대한 것이며 화면 (db, 파일) 또는 의존하지 않아야했습니다.

내 질문은, 일반적으로 수레 / 소수 / 더블을 사용한 장소는 어디입니까? 그래서 저는이 문제를 조심해야합니다. 돈으로 long을 사용하고 센트 단위로 값을 저장합니다. 게임에서 객체의 속도를 위해 정수를 추가하고 픽셀을 움직일 필요가 있는지 알기 위해 값을 나누거나 비트 시프트합니다. (저는 6502 일 안에 물체를 움직였습니다. 우리는 나누거나 떠 다니지 않았지만 변화했습니다.)

그래서 나는 대부분 궁금했다.


10
내가 내 모기지에 지불하는이자가 12.6로 남아 있고 13이되지 않는다는 점이 매우 중요하기 때문에 왜냐하면 왜냐하면 cos 13은 좋은 반올림 숫자입니다.
Chani

1
"저는 6502를 매우 일찍 배웠으며 대부분의 프로그램에서 플로트가 필요하지 않았습니다. 객체의 속도를 위해 정수를 추가하고 픽셀을 이동할지 여부를 알기 위해 값을 나눕니다." 이것은 돈을 긴 센트로 표현하는 것을 제외하고는 현대 업무에서 이러한 작업을 수행하는 매우 특이한 방법입니다.
jprete 2016 년

컴퓨터가 밀리 센트를 이해하는 것이 좋습니다.
tylermac

1
또는 분수를 사용할 수 있는데 왜 소수점을 사용합니까?
tylermac

6
@Scrooge-아이러니하게도 float에서 0.6을 나타낼 수 없습니다.
Martin Beckett 2016 년

답변:


28

대부분의 경우 정수 보다 정확하기 때문입니다.

지금 어때요? "게임에서 물체의 속도를 위해 ..."이 경우에 좋은 예입니다. 총알과 같이 매우 빠른 물건이 필요하다고 가정 해보십시오. 정수 속도 변수를 사용하여 동작을 설명하려면 속도가 정수 변수 범위에 있는지 확인해야합니다. 즉, 임의로 미세한 래스터를 가질 수 없습니다.

그러나 시계의 시침과 같이 매우 느린 물체를 묘사 할 수도 있습니다. 총알 객체보다 약 6 배 더 느리기 때문에 첫 번째 ld (10⁶) ≈ 20 비트는 0이므로 short int시작부터 유형을 배제 합니다. 좋아, 오늘 우리는 long어디에나 있고, 여전히 편안한 12 비트로 남겨 둡니다. 그럼에도 불구하고 클럭 속도는 소수점 이하 네 자리까지만 정확합니다. 그다지 좋은 시계는 아니지만 게임에는 문제가 없습니다. 래스터를 기존보다 훨씬 더 거칠게 만들고 싶지는 않습니다.

... 언젠가 새롭고 더 빠른 유형의 객체를 소개해야 할 경우 문제가 발생합니다. "헤드 룸"이 남아 있지 않습니다.

플로트 유형을 선택하면 어떻게됩니까? 동일한 크기의 32 비트이지만 이제 모든 객체에 대해 최대 24 비트의 정밀도를 갖습니다 . 즉, 시계는 몇 년 동안 최신 상태를 유지하기에 충분한 정밀도를 가지고 있습니다. 총알은 더 높은 정밀도를 갖지 않지만 어쨌든 몇 초 동안 만 "살아"있기 때문에 실제로는 쓸모가 없습니다. 그리고 당신이 설명하려는 경우에도 훨씬 더 빨리 객체 문제의 모든 종류에 (왜 빛? 아니 문제의 속도) 또는 훨씬 느린 사람을하지 않습니다. 당신은 확실히 게임에서 그런 것들을 필요로하지는 않지만 때로는 물리 시뮬레이션에서합니다.

부동 소수점 숫자를 사용하면 항상 동일한 정밀도를 얻을 수 있습니다. 그러한 선택의 필요성은 오류가 발생하기 쉽기 때문에 아마도 가장 중요한 점일 것입니다.


정수는 완벽하게 정확합니다. 부정확 한 계산은 잘못된 계산에 의존합니다.
fjdumont

15
정수는 실제로 정수 (ℤ) 숫자를 나타내는 데 사용하는 경우에만 완벽하게 정확합니다. 다른 것을 나타내는 것은 실제로 잘못된 계산을 의미합니다. 이러한 경우 두 가지 가능성이 있습니다. 실제로 표시하려는 숫자에 완벽하게 맞는 유형을 정의하십시오. 예를 들어 Mathematica가 할 수 있습니다. 그러나 그것은 매우 복잡하고 시간이 많이 걸리며 실제로는 완벽한 정밀도가 필요하지 않기 때문에 노력할 가치가 없습니다. 그러나 당신은 좋은 정밀도 를 필요로합니다 . 그리고 그것은 float가 일반적으로 정수보다 더 나은 일을하는 곳입니다.
leftaroundabout

53

개별 값이 아닌 연속적인 값을 설명 할 때 사용합니다 . 그것보다 설명하기가 더 복잡하지 않습니다. 소수점이있는 값이 연속적이라고 가정하는 실수를하지 마십시오. 페니 추가와 같이 한 번에 덩어리로 바뀌면 불 연속적입니다.


28

여기에 두 가지 질문이 있습니다.

어쨌든 누구나 부동 소수점 수학이 필요한 이유는 무엇입니까?

Karl Bielefeldt가 지적했듯이 부동 소수점 숫자를 사용하면 물리적 세계뿐만 아니라 비즈니스 및 금융과 같은 곳에서도 연속적인 수량을 모델링하여 모든 곳에서 찾을 수 있습니다.

필자는 프로그래밍 경력에서 화학, AutoCAD 작업, 재무 예측을 위해 Monte Carlo 시뮬레이터 작성 등 많은 분야에서 부동 소수점 수학을 사용했습니다. 실제로 David E. Shaw라는 이름의 한 사람이 부동 소수점 기반 과학 모델링 기법을 월스트리트에 적용하여 수십억 달러를 벌었습니다.

물론 컴퓨터 그래픽도 있습니다. 저는 사용자 인터페이스를위한 아이 캔디 개발에 대해 상담하고 있으며, 오늘날 부동 소수점, 삼각법, 미적분학 및 선형 대수학에 대한 확실한 이해없이이를 시도하는 것은 주머니칼로 총 싸움을하는 것과 같습니다.

왜 float 대 double이 필요 합니까?

IEEE 754 표준 표현으로, 32 비트 부동 소수점 10의 범위에서 7 개 소수점 정밀도의 숫자 및 지수에 대해 제공 -38 (10)에 (38) . 64 비트 double은 약 15 자리의 십진 정확도와 10 -307 ~ 10 307 범위의 지수를 제공합니다 .

누군가가 합리적으로 필요로하는 것이라면 float가 충분할 것 같지만 그렇지 않습니다. 예를 들어, 많은 실제 수량은 10 진수 7 자리 이상으로 측정됩니다.

그러나 더 미묘하게도 구어체 적으로 "라운드 오프 오류"라는 문제가 있습니다. 이진 부동 소수점 표현은 분수 부분에 1/2, 1/4, 3/4 등 2의 거듭 제곱 인 분모가있는 값에만 유효합니다. 1/10과 같은 다른 분수를 나타내려면 "라운드" 가장 가까운 이진 분수에 대한 값이지만 약간 잘못되었습니다. "반올림 오류"입니다. 그런 다음 그 부정확 한 숫자에 대해 수학을 수행하면 결과의 부정확성이 처음 시작한 것보다 훨씬 나빠질 수 있습니다. 때로는 오류 백분율이 곱해 지거나 기하 급수적으로 쌓일 수도 있습니다.

어쨌든, 이진 숫자가 많을수록 반올림 이진 표현이 표현하려는 숫자에 더 가까워 지므로 반올림 오류가 작아집니다. 그런 다음 수학을 할 때 작업 할 숫자가 많으면 누적 반올림 오류가 문제가되는 곳까지 쌓이기 전에 더 많은 작업을 수행 할 수 있습니다.

실제로, 십진수 15 자리로 된 64 비트 복식은 많은 응용 프로그램에 충분하지 않습니다. 1985 년에 80 비트 부동 소수점 숫자를 사용하고 있었으며 IEEE는 이제 128 비트 (16 바이트) 부동 소수점 유형을 정의합니다.


2
+1 Bob 천문학 용 망원경과 같은 고해상도 제어 시스템에 대한 나의 경험은 용어를 정렬하지 않으면 64 비트 복식으로는 충분하지 않다는 것입니다. 화재 제어 및 장거리 탐색을위한 저두
팀 Williscroft

20

돈을 다루는 모든 곳에서 값을 정수 (센트)로 저장해야한다는 것은 일반적인 오해입니다. 온라인 상점과 같은 간단한 경우에는 사실이지만, 더 발전된 것이 있으면별로 도움이되지 않습니다.

예를 들어 보자. 개발자는 연간 $ 100,000를 벌고 있습니다. 그의 정확한 월급은 얼마입니까? 정수를 사용하면 $ 8333.33 (¢ 833333)의 결과에 12를 곱한 값이 $ 99,999.96이됩니다. 정수로 유지 했습니까? 아뇨.

은행은 항상 10 진수 / 정수 값을 사용합니까? 글쎄, 그들은 거래 부분을 수행합니다. 그러나 예를 들어 실제 거래를 추적하는 것을 제외하고 투자 은행과 대화를 시작하자마자 다른 모든 것이 떠 오릅니다. 모두 사내 코드이기 때문에 그것을 볼 수는 없지만 QuantLib 에서 정점에 도달 할 수 있습니다 .

왜 수레를 사용합니까? 제곱근, 로그, 정수가 아닌 지수 등의 함수를 사용할 때는 십진수를 사용하는 것이 전혀 도움이되지 않습니다. 물론 부동 소수점은 십진법보다 빠릅니다.


1
@Job-소수점과 부동 소수점은 매우 다릅니다. 당신은 소수 유형에 정확히 0.1을 저장할 수 있지만 부동 또는 더블.
Scott Whitlock

3
다른 질문이 있습니다. $100,000/12플로트 를 지불 하고 사용한 경우. 결과가 정확히 $ 100,000 인 이유는 무엇입니까? 누군가 지불 할 때마다 왜 float (또는 10 진수)을 반올림 또는 내림하지 않습니까? 수표 (1/2 또는 1/3 센트를 할 수 없음) 또는 직접 입금 (동일한 제한이 있다고 가정)을 작성할 때에 대해 이야기하고 있습니다.

@acid : >>> x = 100000 / 12.0 >>> x * 12 100000.0
vartec

내 의견을 다시 읽으시겠습니까? 내 질문은 소프트웨어를 사용하여 매월 수표를 만들 때입니다. 1 년 후 1/2 센트를 지불 할 수 없기 때문에 그 사람은 1 년 후 어떻게 전액을 얻습니까?

2
@acid : 정수, 십진수 또는 부동 소수점으로 나누기 또는 반올림을 사용하더라도 직선 나누기를 사용할 수 없습니다. 그것은 십진수를 사용하는 것이 그 경우에 도움이되지 않는 요점입니다.
vartec

4

지금까지 설명한 내용은 모든 입력 및 출력을 제어하는 상황에 대한 완벽한 해결 방법입니다 .

실제로는 그렇지 않습니다. 데이터를 어느 정도 정확한 값으로 제공하고 동일한 형식으로 데이터를 리턴 할 것으로 예상하는 시스템에 대처할 수 있어야합니다. 이러한 경우 이러한 문제 발생합니다.

사실 당신이 나열한 트릭을 사용하더라도 이러한 문제가 발생합니다. 가격에 대해 17.5 %의 세금을 계산할 때 가치를 달러 또는 센트로 저장하든 분수 센트를 얻게됩니다. 세금을 충분히 지불하지 않으면 세금 담당자가 매우 화를 내므로 반올림이 정확해야합니다. 올바른 money유형 ( 사용하는 언어가 무엇이든)을 사용하면 고통의 세계에서 벗어날 수 있습니다.


돈 유형은 무엇입니까? (언어 또는 참조 링크) 왜 '올바른'유형입니까? 128 비트 이상인가? 내 다른 사람들이 왜 '트릭'을 사용하는 것이 잘못 되었습니까? 당신은 정수로 퍼센트를 가지고 있습니다. .175를 곱하면 정수를 얻고 원하는대로 사용할 수 있습니다. 귀하의 예를 생각하면 float가 충분한 정밀도로 내 가치를 유지할 수 있다고 생각하지만 0.3f = = 0.3d가 거짓이라는 것에 대해 걱정할 필요가 없습니다. -edit- 및 +1

1
@ acidzombie24-특정 유형을 의미하지는 않았지만 언어 유형에 따라 돈 가치를 나타내는 데 사용됩니다. 또한 10 센트가 있고 0.175를 곱하면 1.75 센트가 있습니다-정수 산술로 어떻게 처리합니까? 1 센트 또는 2 센트입니까? 잘못하면 고객이 세금 담당자에게 많은 돈을 소유하게 될 수 있습니다.
ChrisF

정확한 숫자와 부정확 한 숫자를 혼합해서는 안되므로 10 (정수)에 .175 (실수 / 부동 수)를 곱하면 안됩니다. 결과는 정확하지 않습니다. 다시 말해, 정확한 숫자 체계에서 .175와 같은 값은 존재하지 않으므로 이것은 의미가없는 계산입니다. 더 나은 솔루션은 10000에 175를 곱하고 적절한 곳에 소수점을 수동으로 삽입하는 것입니다.
베리 브라운

8
@ 배리-알아요 나는 당신이 얻는 문제의 유형을 설명하려고했습니다. 또한 세율이 17.5 %이고 비용이 10 센트 인 품목에 대해 세금을 계산해야하는 경우 0.175와 같은 값이 존재합니다.
ChrisF

1
@acidzombie : 돈에 사용하는 올바른 유형은 고정 소수점 10 진수 (소수점 최소 4 자리)입니다. if, ands, 또는 buts는 없습니다. 실제로 돈 가치를 센트로 저장 하는 것만으로는 충분 하지 않습니다 . 실제로는 2 포인트의 정밀도 만 제공하기 때문입니다.
Aaronaught

3

"하나님은 정수를 만드셨고, 다른 모든 것은 사람의 일입니다." – 레오폴드 크로네 커 (1886).

정의에 따라 다른 종류의 숫자는 필요 하지 않습니다 . 프로그래밍 언어에 대한 튜링 완전성은 다양한 종류의 숫자 사이의 간단한 관계를 기반으로합니다. 정수 (a / k / 자연수)로 작업 할 수 있다면 무엇이든 할 수 있습니다.

질문은 필요 하지 않기 때문에 의문의 여지가 있습니다. 아마도 당신은 편리하거나 최적이거나 싼 곳이나 다른 곳을 원하십니까?


7
우리는 또한 이론 이론과 빈 집합 만 사용하여 구성 할 수 있기 때문에 정수를 생략 할 수도 있습니다. 그러나 튜링의 완전성에 대한 논쟁은 학문적 축소주의가 극도로 나아갑니다.
Bob Murphy

4
또한 Turing 완성도는 컴퓨팅에만 적용됩니다. Cauchy 시퀀스의 수렴에 닫히지 않기 때문에 정수 나 합리적인 값도 수학적으로 완전하지 않습니다. 그래서 크로네 커는 열기로 가득 차있었습니다. 정수를 포함하는 완전한 미터법 공간을 원한다면 현실을 얻어야합니다. xkcd.com/849
Bob Murphy

1
@Bob Murphy : "학술 축소주의가 극단으로 옮겨졌다". 정확하게. 질문은 가난하며 가능한 대답으로 이어집니다.
S.Lott

2

문장에서 부동 소수점 10 진수 유형은 정수 값 (및 모든 컴퓨터가 이진 레벨에서 처리하는 방법을 알고 있으며 이진에는 소수점이 없음)과의 변환을 캡슐화합니다. 십진수 계산을위한 인터페이스를 이해합니다.

솔직히 정수를 사용하여 십진법을 수행하는 방법을 알고 있기 때문에 부동 소수점이 필요 없다고 말하는 것은 산술을 오랫동안 사용하는 방법을 알고 있다고 말하는 이유는 무엇입니까? 그래서 당신은 개념을 알고 있습니다. 브라보. 항상 그 지식을 행사해야한다는 의미는 아닙니다. 비 이진-비즈에게는 시그 무화과를 정수로 변환하는 대신 단순히 3.5 + 4.6 = 8.1이라고 말하는 것이 더 빠르고 저렴하며 이해하기 쉽습니다.


1

부동 소수점 유형의 주요 이점은 런타임 관점에서 2 개 또는 3 개의 형식 (80 비트 형식을 지원하는 더 많은 언어가 필요함)이 대부분의 계산 목적에 충분하다는 것입니다. 프로그래밍 언어가 고정 소수점 유형의 제품군을 쉽게 지원할 수있는 경우 주어진 수준의 성능에 필요한 하드웨어 복잡도는 부동 소수점보다 고정 소수점 유형에서 더 낮습니다. 불행히도, 그러한 지원을 제공하는 것은 "쉬운"과 거리가 멀다.

프로그래밍 언어가 애플리케이션 수치 요구의 98 %를 효율적으로 충족 시키려면 수십 가지 유형을 포함하고 수백 가지 조합에 대한 정의 된 연산을 제공해야합니다. 또한, 프로그래밍 언어가 훌륭한 고정 소수점 지원을 가지고 있어도 일부 응용 프로그램은 여전히 ​​부동 소수점을 요구하기에 충분히 넓은 범위에서 대략 일정한 상대 정밀도를 유지해야합니다. 어떤 경우 든 부동 소수점 수학이 필요할 때를 감안할 때 하드웨어 공급 업체가 2 ~ 3 개의 부동 소수점 형식으로 수학 성능에 초점을 맞추고 코드가 합리적으로 잘 작동 할 때마다 해당 형식을 사용하면 일반적으로 더 나은 결과를 얻을 수 있습니다 고정 소수점 수학의 동작을 최적화하려고 시도하는 것보다 "벅".

또한 고정 소수점 연산은 32 비트 프로세서보다 8 비트 및 16 비트 프로세서에서 더 유리합니다. 8 비트 프로세서에서 32 비트로 충분하지 않은 상황에서 40 비트 유형은 32 비트 유형보다 25 % 더 많은 공간과 25-50 % 더 많은 시간이 소요되며 37.5 %가 필요합니다. 64 비트 유형보다 적은 공간과 37.5-60 % 적은 시간. 32 비트 플랫폼에서 32 비트 유형으로 충분하지 않은 경우 64 비트 미만을 사용해야 할 이유가 거의 없습니다. 48 비트 고정 소수점 유형이 적합하면 64 비트 "double"은 고정 소수점 유형과 마찬가지로 작동합니다.


0

일반적으로 사용에 매우주의해야합니다. 간단한 계산에서도 발생할 수있는 정밀도 손실을 이해하는 것은 어려운 일입니다. 예를 들어, 이와 같은 숫자 목록을 평균화하는 것은 매우 나쁜 생각입니다.

double average(List<Double> data) {
  double ans = 0;
  for(Double d : data) {
    ans += d;
  }
  return ans / data.size();
}

그 이유는 충분히 큰 목록의 경우 충분히 커지면 기본적으로 모든 데이터 포인트가 손실 ans되기 때문입니다 (예 : this 참조 ). 이 코드의 문제는 작은 목록의 경우 아마도 작동 할 것입니다. --- 그것은 규모에 달려 있습니다.

개인적으로, 나는 다음과 같은 경우에만 그것들을 사용해야한다고 생각합니다. b) 결과가 나올 가능성에 대해 신경 쓰지 않습니다 (무엇을하고 있는지 실제로 알지 않는 한).


-1

한 가지 생각은 정수 범위 밖의 값을 처리해야 할 때 부동 또는 이중 표현을 사용한다는 것입니다.

오늘날의 아키텍처는 (대략적으로) +/- 2,147,483,647 (32 비트) 또는 +/- 9,223,372,036,854,775,807 (64 비트)의 부호있는 정수 범위를 갖습니다. 부호없는 것은 2 배로 확장합니다.

IEEE 754 플로트는 (대략) +/- 1.4 × 10 ^ -45에서 3.4 × 10 ^ 38로 이동합니다. 여기서는 많은 조건과 세부 사항이 생략 된 +/- 5 × 10−324 ± 2.225 × 10 ^ -308 범위로 이중 확장됩니다.

물론 가장 놀랄만 한 이유는 -0 ;-)을 나타내야 할 수도 있기 때문입니다.


주로 위키피디아 기사의 숫자이며 설명을위한 것입니다. -0을 제외하고, 그것은 단지 재미를위한 것입니다.
Stephen

문제는 그 거대한 범위에 정수가 많지 않아 전혀 표현되지 않습니다.
Barry Brown

@BarryBrown 물론입니다. "많은 조건과 사양은 생략되었습니다."
Stephen

-1

일반적인 이유는 JVM이 일반적으로 기본 하드웨어 지원을 사용 하기 때문에 빠르기 때문입니다 (strictfp를 사용하지 않는 한).

strictfp의 의미는 https://stackoverflow.com/questions/517915/when-to-use-strictfp-keyword-in-java 를 참조 하십시오 .


부동 소수점 수학이 정수 수학보다 빠릅니까? 부동 소수점 계산은 정수 계산보다주기가 적은 프로세서는 무엇입니까?
this.josh

1
@ this.josh는 숫자에 포함 된 자릿수에 따라 크게 달라집니다. 또한 정수는 중요하거나 중요하지 않은 정확하게 나눌 수 없습니다.

-2

그렇기 때문에 256 비트 운영 체제가 필요합니다.

Plank 길이 (측정 할 수있는 최소 거리) = 10 ^ -35m
관측 가능한 유니버스는 14 ^ n parsecs = 10 ^ 25m
이므로 200 비트의 정밀도 만 있으면 Plank 길이 단위를 정수로 측정 할 수 있습니다.


2
-1 : 관측 가능한 우주보다 더 큰 규모로 사물을 시뮬레이션하는 경우 어떻게됩니까?
amara

2
@sparkleshy, 그것이 FAR 포인터의 목적입니다!
Martin Beckett
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.