2012-05-04 3 views
5

정말 이상한 ¿ 버그에 직면하고 있습니까? mysql + php에서 지금.MySQL round weird bug

  • "필드가"11.5
  • $의 phpvar 1.15

MySQL의 쿼리입니다 : 다음 예제 난 내 문제를 설명하려고 여러 필드를 사용하고, 간단한 선택이다 :

select round(field * " . $phpvar . " ,2) as a1, 
     round(field * 1.15 ,2) as a2, 
     round(11.5 * " . $phpvar . " ,2) as a3, 
     round(11.5 * 1.15 ,2) as a4, 
     field * " . $phpvar . " as a5 
from ... 

괜찮습니까? 13.23을 얻으려고합니다. "field" * $phpvar = 13.225, 그래서 라운드 (13.225,2)를 사용하면 13.23을 얻습니다. 맞습니까? 음, 예, 아니오.

질의 결과 :

  • A1 [라운드 (".. $ phpvar"필드 * 2)] => 13.22
  • A2 [라운드 (필드 * 1.15, 2) => 13.22
  • A3 [라운드 (11.5 * ". $ phpvar.", 2) => 13.23
  • A4 [라운드 (11.5 * 1.15, 2) => 13.23
  • A5 [필드 * ". $ phpvar. "] => 13.225 (회전 없음)

무엇이 누락 되었습니까? 어떻게 가능합니까, "필드"를 사용할 때, 제 결과는 가짜 라운드가됩니까?

+1

데이터베이스에 정의 된 필드는 어떻게됩니까? – Anigel

+0

반올림하지 않고 필드 * 1.15 및 11.5 * 1.15를 선택하면 a6 및 a7과 같이 결과가 게시됩니다. – jishi

+0

대신'ceil()'을 사용 하시겠습니까? – Nick

답변

6

문제는 DOUBLE 및 FLOAT 값이 저장되는 방법입니다.

11.5 또는 22.475 coul과 같은 값은 11.499999999999 ~ 22.475000000000000001과 같은 근사값으로 저장되므로 일부 계산 또는 반올림으로 인해 잘못된 결과가 발생할 수 있습니다.

항상 float 값을 DECIMAL coulmn 유형에 저장하는 것이 더 좋습니다. 여기서 값은 모든 십진수로 정확하게 저장되며 근사값이 아닙니다. MySQL의의 DECIMAL 유형을 사용 encoded (예 : 후자의 두에 예제의 네에서 1.1511.5 등)

+0

감사합니다. DECIMAL이 올바르게 작동합니다. 앞으로의 일을 염두에 두겠습니다. – ipronet

+0

@ipronet 환영합니다! – shadyyx

+0

@ipronet 또한 도움이 되었다면 답을 표시하십시오. 고맙습니다! – shadyyx

5

정확한 숫자 리터럴. 처음 2 개의 실시 예에서

, 예컨대 리터럴 field (DOUBLE의 유형)의 승산 결과는 8-byteIEEE Standard 부동 소수점 표현 (즉 binary64)를 사용하여 저장되는 다른 DOUBLE이다. 그러나,이 표현 13.225 누구 비트 의미 0x402A733333333333로 인코딩 : 소수점 2 자리이 결과를 반올림 그러므로

 
    (-1)^0 * 1.6531249999999999555910790149937383830547332763671875 * 2^3 
=   13.2249999999999996447286321199499070644378662109375000 

13.22하지 13.23을 산출 :

 
Sign   : 0b0 

Biased exponent: 0b10000000010 
       = 1026 (representation includes bias of +1023, therefore exp = 3) 

Significand : 0b[1.]1010011100110011001100110011001100110011001100110011 
       = [1.]6531249999999999555910790149937383830547332763671875 
        ^hidden bit, not stored in binary representation 

이 총점.

후자의 두 예제에서 사용 된 두 개의 리터럴과 같은 두 개의 DECIMAL 유형을 사용하여 곱셈을 수행하면 DECIMAL이됩니다.이 표현에서 13.225binary-coded decimal 형식으로 정확한 정밀도로 인코딩되므로 반올림 연산은 13.23으로 예상됩니다. 그들은 대략 아니라 정확한 값으로 저장하기 때문에

부동 소수점 숫자는 때때로 혼동을 원인 : MySQL manual에서 언급 한 바와 같이

. SQL 문에 쓰여지는 부동 소수점 값은 내부적으로 표현 된 값과 다를 수 있습니다. 비교에서 부동 소수점 값을 정확하게 처리하려고하면 문제가 발생할 수 있습니다. 또한 플랫폼 또는 구현 종속성의 영향을받습니다. FLOATDOUBLE 데이터 형식은 이러한 문제의 영향을받습니다. DECIMAL 컬럼의 경우, MySQL은 정밀도 65 진수로 연산을 수행하므로 가장 일반적인 부정확성 문제를 해결할 수 있습니다.

정확도가 정확하다면 DECIMAL이 요구 사항에 더 적합 할 수 있습니다. DOUBLE의 범위/성능이 필요하지만 원하는 반올림 결과를 계속 나타내려면 반올림하기 전에 DECIMAL으로 곱한 결과 CONVERT을 입력하면됩니다.