2016-07-13 7 views
0

나는 mysql 데이터베이스에서 금리를 다룬다. 이들은 두 배로 저장되며 일반적으로 소수점 1/1000 (예 : 4.657)이지만 때로는 더 많습니다. 때로는 이것들에 대해서만 백분의 일 장소 (예 : 4.65)에보고해야하지만 나는 이것을 둘 수 없다 - 나는 그것을 잘라야 할 필요가있다. 그래서, 5.6575 %의 데이터베이스에서 내 이자율, 5.65 %가 아니라 5.65 %를 얻을 필요가있다.MYSQL 수치 함수 (floor, truncate)가 예상대로 작동하지 않습니다 - 설명?

일반적으로 TRUNCATE (int_rate, 2)는 정상적으로 작동합니다. 이것은 지금까지 아무런 문제없이 나를 위해 일해 왔습니다.

8.0300 %, 8.0400 %, 9.0300 %, 9.0400 %, 10.0300 %, 10.0400 % ... 등의 금리에 문제가 있습니다. 금리가 8 % 이상이고 3 또는 4는 100 위이고 나머지는 0입니다.

8.04가 DB에 있으면 TRUNCATE (int_rate, 2) 할 때 8.03을 반환합니다. FLOOR (int_rate * 100)/100

숫자를 하드 코딩하고 DB에서 가져 오지 않으면 TRUNCATE (8.04, 2) 또는 TRUNCATE가 제대로 자릅니다. (8.0400, 2)는 예상대로 8.04를 반환합니다.

4.0400 %는 훌륭하게 작동합니다. 그래서 8.0600 %입니다! 왜 이러한 결과를 주는가? 또한 누군가가이 오류없이이 작업을 수행 할 수있는 방법을 제안 할 수 있다면 그것은 경이로운 것입니다!

의 MySQL은 : 5.0.95

+0

부동 소수점 숫자는 대략적인 '8.04'는 실제로'8.0399999999'와 같은 것이므로, 그것을 잘라내는 것은'8.03'을 반환합니다. – Barmar

+0

'8.04'를 하드 코딩하면 'DOUBLE'이 아닌 'DECIMAL'로 해석되므로 정밀도를 잃지 않습니다. 왜 테이블에'DECIMAL' 타입을 사용하지 않습니까? 이것은 정밀도를 잃을 수없는 응용 프로그램을 위해 설계되었습니다. – Barmar

답변

0

PHP floating point numbers에서 촬영 :

부동 소수점 숫자는 정밀도를 제한했다. 시스템에 따라 다르지만 일반적으로 PHP는 IEEE 754 배정도 형식을 사용합니다.이 형식은 1.11e-16 정도의 반올림으로 인해 최대 상대 오차가 발생합니다. 기본이 아닌 산술 연산은 더 큰 오류를 줄 수 있으며 물론 여러 작업이 혼합 될 때 오류 전파를 고려해야합니다.

또한, 기수 10에서 부동 소수점 숫자로 정확하게 표현할 수있는 유리수 (예 : 0.1 또는 0.7)는 기수 2의 부동 소수점 숫자로 정확하게 표현되지 않으며 내부 2 가수. 따라서 정밀도를 약간 떨어 뜨리지 않고 내부 바이너리로 변환 할 수 없습니다. 이는 내부 표현이 7.99999999999991118 ...

과 같기 때문에 floor ((0.1 + 0.7) * 10)는 예상되는 8 대신 대개 7을 반환합니다. 가능한 수정 : TRUNCATE 대신 ROUND를 시도 했습니까?

+0

질문은 PHP가 아니라 MySQL에 관한 것입니다. 이유는 동일하지만 마지막 단락은 실제로 적용 할 수 없습니다. – Barmar

+0

@Barmar ... 당신 말이 맞아 ... 나는 그것을 제거했다. 대답은 문제를 설명하고, 나는 소스를 언급하지 않고 웹 사이트에서 cut-n-paste를하고 싶지 않다. – patrick

+0

@Barmar : 합법적으로 반올림 할 수 없기 때문에 라운드를 사용할 수 없습니다. 누군가 4.239의 이자율을 가지고 있다면 4.24가 아니라 4.23이 필요합니다. 내가 얻지 못하는 한 가지. 이자율이 8.04- 인 경우 int_rate * 100 = 804 floor (int_rate * 100) = 803 int_rate가 4.56789 * 100이므로 456.789이므로 바닥을 사용해야합니다. – Charistine