PHP 정밀도 계산 문제

单线程
풀어 주다: 2020-05-07 15:44:27
원래의
172명이 탐색했습니다.

php 정밀도 계산 문제

PHP의 흥미로운 현상을 살펴보겠습니다. var_dump( intval(0.58 * 100) ) 이 코드가 어떤 결과를 출력할지 추측해 보세요.

출력 결과가 58

왜일까요? 이것은 모두 부동 소수점 연산으로 인해 발생합니다.
사실 이러한 결과는 언어 버그가 아니라 언어의 구현 원리와 관련이 있습니다. js의 모든 숫자는 정수를 포함하여 실제로는 모두 배정밀도(double) 유형인 Number로 통일됩니다.

그리고 PHP는 int와 float를 구별합니다. 어떤 언어를 사용하더라도 부동소수점 연산이 포함되는 한 비슷한 문제가 있으므로 사용 시 주의가 필요합니다.

예를 들어 64비트 길이(이중 정밀도)를 사용하는 부동 소수점 숫자는 1개의 부호 비트(E), 11개의 지수 비트(Q) 및 52개의 가수 비트(M)로 표시됩니다(총 64개).

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

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

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

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

0.58의 이진 표현은 기본적으로(52비트)입니다. 0010100011110101110000101000111101011100001010001111 0.57(52비트)의 이진 표현은 기본적으로 00100011110101입니다. 110000101000 1111010111000010100011110

그리고 둘의 이진수는 다음과 같습니다. 이 52비트로만 계산하면 다음과 같습니다.

0.58 -> 0.579999999999999960.57 -> 0.5699999999999999

0.58 * 100의 구체적인 부동 소수점 곱셈은 자세히 고려하지 않으므로 막연하게 살펴보겠습니다. 암산으로... 0.58 * 100 = 57.9999999 99

그러면 intval해 주세요. 당연히 57입니다...

이 문제의 핵심은 다음과 같습니다. 컴퓨터의 이진수 표현에서는 무한합니다."

PHP 부동 소수점 형식은 +-*%/를 수행하고 있습니다. 부정확성 문제가 있습니다

우리는 일반적으로 사용되는 다음과 같은 부동 소수점 연산의 부정확성 문제를 해결할 수 있습니다. 정밀도 함수:

bcadd — 두 개의 고정밀도 숫자 더하기

bccomp — 두 개의 고정밀도 숫자 비교 숫자, -1, 0, 1 

bcdiv — 두 개의 고정밀도 숫자 나누기

bcmod — 나머지 찾기 고정밀 숫자의

bcmul — 두 개의 고정밀 숫자 곱하기

bcpow — 고정밀 숫자 찾기 Power

bcpowmod — 고정밀 숫자의 거듭제곱을 찾고 정수론에서 매우 일반적으로 사용되는 모듈러스 찾기

bcscale — Linux의 "scale="에 해당하는 기본 소수점 수를 구성합니다. bc

bcsqrt — 고정밀 숫자의 제곱근 찾기

bcsub — 두 고정밀 숫자 빼기


위 내용은 PHP 정밀도 계산 문제의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
1
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!