>백엔드 개발 >PHP 문제 >PHP가 부동 소수점 숫자를 계산할 수 없으면 어떻게 해야 합니까?

PHP가 부동 소수점 숫자를 계산할 수 없으면 어떻게 해야 합니까?

藏色散人
藏色散人원래의
2021-11-19 09:50:161685검색

php는 컴퓨터의 기본 바이너리가 부동 소수점 숫자를 정확하게 표현할 수 없기 때문에 부동 소수점 숫자를 계산할 수 없습니다. 해결책은 정확한 계산을 위해 PHP의 BC 고정밀 함수 라이브러리와 같은 클래스 라이브러리나 함수 라이브러리를 사용하는 것입니다.

PHP가 부동 소수점 숫자를 계산할 수 없으면 어떻게 해야 합니까?

이 기사의 운영 환경: Windows 7 시스템, PHP 버전 7.1, DELL G3 컴퓨터

PHP가 부동 소수점 숫자를 계산할 수 없으면 어떻게 해야 합니까?

php의 부동 소수점 계산 문제

부동 소수점 계산에 PHP의 +-*/를 사용하면 echo intval(0.58*100); 58 대신 57을 인쇄하십시오. 이것은 실제로 기본 컴퓨터 바이너리가 부동 소수점 숫자를 정확하게 표현할 수 없는 버그입니다. 또한 Python을 사용하여 이 문제가 발생했습니다. 그래서 기본적으로 대부분의 언어는 정확한 계산을 위해 클래스 라이브러리나 함수 라이브러리를 제공합니다. 예를 들어, PHP에는 BC 고정밀 함수 라이브러리가 있습니다.

 Example

<?php    
$f = 0.58;    
var_dump(intval($f * 100)); 
//为啥输出57
?>

 왜 출력이 57인가요? PHP에 버그가 있는 걸까요?

 bugs.php는 물론이고 비슷한 질문을 하는 분들이 많아서 많은 학생들이 이런 질문을 받았던 것 같아요. 인터넷에 물어보세요...

이 이유를 이해하려면 먼저 부동 소수점 숫자(IEEE 754)의 표현을 알아야 합니다. 64비트 길이(이중 정밀도)를 예로 들어 부동 소수점 숫자는 다음을 사용합니다. 1개의 부호 비트(E), 11개의 지수 비트(Q), 52비트 가수(M)는 총 64비트를 나타냅니다.

부호 비트: 가장 높은 비트는 데이터의 부호를 나타내고, 0은 양수를 나타냅니다. 1은 음수를 나타냅니다.

 지수 비트: 2를 밑으로 하는 데이터의 거듭제곱을 나타내며, 지수는 오프셋 코드로 표현됩니다.

 가수: 데이터의 소수점 이하 유효 숫자를 나타냅니다.

 여기서 핵심은 표현입니다. 이진수로 표현하면 Baidu에서 검색할 수 있습니다. 여기서는 자세히 설명하지 않겠습니다. 우리가 이해해야 할 핵심은 이진수 표현의 경우 0.58이 무한히 긴 값이라는 것입니다. 다음 숫자는 암시적 1)을 생략합니다..

0.58의 이진 표현은 기본적으로(52비트)입니다. 00101000111101011100001010001111010111000010100011110 0.57(52비트)의 이진 표현은 기본적으로 00100011110101입니다. 11000010100011110101 11000010100011110 그리고 둘의 이진수는 다음을 통해서만 계산됩니다. 이 52비트는 다음과 같습니다. www.111cn.net

0.58 -> 0.57999999999999960.57 -> 0.569999999999999 0.58 * 100의 구체적인 부동 소수점 곱셈에 대해서는 자세히 살펴보지 않겠습니다. (부동소수점) 암산으로 막연하게 살펴보겠습니다... 0.58 * 100 = 그럼 이제 PHP 버그인 줄은 몰랐는데 이게 바로...

PHP 부동 소수점 처리에서 +-*%/에 부정확한 부분이 있습니다.

예:

  $a = 0.1;
  $b = 0.7;
  var_dump(($a + $b) == 0.8);

인쇄된 값은 부울 false입니다

PHP 설명서에는 부동 소수점 숫자에 대해 다음과 같은 경고 메시지가 있습니다.

경고

부동 소수점 정밀도

분명히 0.1이나 0.7과 같은 단순한 소수는 약간의 정밀도 손실 없이 내부 이진 형식으로 변환될 수 없습니다. 이로 인해 혼란스러운 결과가 발생할 수 있습니다. 예를 들어, 바닥((0.1+0.7)*10)은 일반적으로 예상되는 8 대신 7을 반환합니다. 결과의 내부 표현은 7.9999999999…와 같기 때문입니다.

 이는 특정 소수를 유한한 자릿수로 정확하게 표현하는 것이 불가능하다는 사실과 관련이 있습니다. 예를 들어, 10진수 1/3은 0.3333333이 됩니다.

그러므로 부동 소수점 숫자 결과가 마지막 자리까지 정확하다고 절대 믿지 말고 두 부동 소수점 숫자가 같은지 비교하지 마세요. 정말로 더 높은 정밀도가 필요하다면 임의 정밀도 수학 함수나 gmp 함수를 사용해야 합니다

코드는 다음과 같습니다:

<?php
$a = 0.1;
$b = 0.7;
var_dump(bcadd($a,$b,2) == 0.8);
  bcadd — 将两个高精度数字相加
  bccomp — 比较两个高精度数字,返回-1, 0, 1
  bcp — 将两个高精度数字相除
  bcmod — 求高精度数字余数
  bcmul — 将两个高精度数字相乘
  bcpow — 求高精度数字乘方
  bcpowmod — 求高精度数字乘方求模,数论里非常常用
  bcscale — 配置默认小数点位数,相当于就是Linux bc中的”scale=”
  bcsqrt — 求高精度数字平方根
  bcsub — 将两个高精度数字相减

 몇 가지 예를 컴파일했습니다

 php BC 고정밀 함수 라이브러리에는 덧셈, 비교, 나눗셈, 위상 뺄셈, 나머지, 곱셈, n승, 기본 소수점 수, 제곱을 구성합니다. 이러한 기능은 전자상거래 가격 계산과 같은 금전적 계산에 더욱 유용합니다.

 참고: 설정된 자릿수와 관련하여 초과된 자릿수는 반올림 대신 폐기됩니다.

추천 학습: "

PHP 비디오 튜토리얼

"

위 내용은 PHP가 부동 소수점 숫자를 계산할 수 없으면 어떻게 해야 합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.