source

이것은 MariaDB의 ROUND 기능의 오동작입니까?

factcode 2022. 11. 26. 13:53
반응형

이것은 MariaDB의 ROUND 기능의 오동작입니까?

현재 작업 중인 프로젝트에서 백엔드와 프런트엔드에서 같은 계산을 하고 있는 자신을 발견했습니다.계산은 두 숫자와 다른 숫자의 비율의 곱을 반올림하는 것이다. 즉, 라운드 대 라운드 표현은 다음과 같은 형식이다.

x / y * n

프런트엔드는 자바스크립트를 사용하고 백엔드는 MariaDB를 사용하고 있습니다.x=41, y=60 및 n=30의 경우 프런트 엔드는 21로 표시됩니다.

41 / 60 * 30

20.5이지만 MariaDB의 구현은ROUND()함수는 내가 이 표현에 전달했을 때 20을 준다!

ROUND(41/60*30,0)

(MariaDB)가 평가하는데도

41 / 60 * 30

올바른 결과 20.199에 도달합니다.

20.5(20.5000)를 MariaDB에 패스하면ROUND()함수, 함수는 올바른 결과 21을 반환합니다!이 미스터리를 (적어도) 다음 SQL 문장으로 요약했습니다.

SELECT 41/60*30, ROUND(41/60*30,0), ROUND(20.5,0), ROUND(20.5000,0)

그 출력은...

여기에 이미지 설명 입력

구현에 문제가 있습니까?ROUND()기능하고 있습니까?

이것은 부동소수점 정밀도 문제입니다.

SELECT CAST(41/60*30 AS DECIMAL(22,20))

다음과 같은 것이 있습니다.

20.49999999000000000000

그래서 반올림하면 20이 나옵니다.이 문제를 해결하려면DECIMAL정확도가 떨어집니다(예:(5,3)) 또는 이중 반올림(예:

SELECT ROUND(CAST(41/60*30 AS DECIMAL(5, 3))) AS crnd, ROUND(ROUND(41/60*30,3)) AS drnd

출력:

crnd    drnd
21      21

나누기 전에 곱하면 부동 소수점을 사용하여 더 정확한 결과를 얻을 수 있습니다.

모두가 지적하고 있는 것처럼 사실이다

부동 소수점 정밀도 문제입니다.

Nick이 제안한 것보다 더 짧고 간단한 회피책(모든 상황에서 효과가 있는지 확실하지 않음)을 발견했을 수 있습니다.우린 뜨는 비율만 캐스팅하고 그게 다...따라서

ROUND(CAST(41/60 AS FLOAT)*30 ,0)

이것은 올바른 결과를 제공한다.

21

그런데 왜 ROUND()가 21과 20을 같은 입력으로 주는지 궁금합니다.누가 가능한 이유를 말해 줄 수 있나요?

언급URL : https://stackoverflow.com/questions/67158065/is-this-a-malfunction-of-the-round-function-in-mariadb

반응형