MySQL圆一半

时间:2016-04-25 14:42:04

标签: mysql rounding

在MySQL中,有可能像PHP那样绕半个特定方式吗?

  • **MenuItem3** = "/VoxeoCXP/DialogMapping/VSN/TelkomKioskService@System?vID=*643434c3c90606f20f9aa6510ff0d08907adf2001613e36cbc80909f59df7be2015010fc0561bc7a*"
  • PHP_ROUND_HALF_UP
  • PHP_ROUND_HALF_DOWN
  • PHP_ROUND_HALF_EVEN

http://php.net/manual/fr/function.round.php

或者我们真的只限于四舍五入?

4 个答案:

答案 0 :(得分:3)

1。来自Oracle文档:

基于MySQL官方文档,舍入功能如下:

  

对于精确值数字,ROUND()使用“从零开始的一半”   或“向最近的方向”规则:具有0.5的小数部分的值   如果为正数或向下,则向上舍入到下一个整数   下一个整数,如果是负数。 (换句话说,它是圆形的   零。)小数部分小于.5的值向下舍入到   如果为正,则为下一个整数;如果为负,则为下一个整数。

http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_round

这意味着我们只能使用舍入函数来舍入。我编写了以下UDF来解决这个限制。

2。代码(在MySQL 5.6中测试):

PHP_ROUND_HALF_ODD

注意:根据项目的需要,可以增加要舍入的数字的值,最多可达65位(在这种情况下,请不要忘记更改{{的所有实例)相应地)}。

https://stackoverflow.com/a/19201329/4949388

3。 PHP中的舍入结果:

enter image description here

http://sandbox.onlinephpfunctions.com/code/054de06b074c2b3ece5fb6e5d4180524cd2207e2

4。单元测试(在SQL中):

CREATE FUNCTION roundHalf (
    numberToRound DECIMAL(20,6),
    roundingPrecision TINYINT(2),
    roundingType ENUM (
        'ROUND_HALF_UP',
        'ROUND_HALF_DOWN',
        'ROUND_HALF_EVEN',
        'ROUND_HALF_ODD'
    )
)
    RETURNS DECIMAL(20,6)
BEGIN
    DECLARE digitEvenOdd TINYINT (2) UNSIGNED DEFAULT 255;
    DECLARE digitPosition TINYINT (2) UNSIGNED DEFAULT 0;
    DECLARE digitToRound TINYINT (2) DEFAULT -1;
    DECLARE roundedNumber DECIMAL(20,6) DEFAULT 0;

    SET digitPosition = INSTR(numberToRound, '.');

    IF (roundingPrecision < 1) THEN

        SET digitPosition = digitPosition + roundingPrecision;
    ELSE

        SET digitPosition = digitPosition + roundingPrecision + 1;
    END IF;

    IF (digitPosition > 0 AND 
        digitPosition <= CHAR_LENGTH(numberToRound)
    ) THEN

        SET digitToRound = CAST(
                SUBSTR(
                numberToRound, 
                digitPosition, 
                1
            ) AS UNSIGNED
        );

        SET digitPosition = digitPosition - 1;

        IF (digitPosition > 0 AND 
            digitPosition <= CHAR_LENGTH(numberToRound)
        ) THEN    

            SET digitEvenOdd = CAST(
                SUBSTR(
                    numberToRound, 
                    digitPosition, 
                        1
                ) AS UNSIGNED
            );
        END IF;
    END IF;

    IF (digitToRound > -1) THEN

        CASE roundingType

            WHEN 'ROUND_HALF_UP' THEN

                IF (digitToRound >= 5) THEN

                    SET roundedNumber = ROUND(numberToRound, roundingPrecision);
                ELSE
                    SET roundedNumber = TRUNCATE(numberToRound, roundingPrecision);
                END IF;

            WHEN 'ROUND_HALF_DOWN' THEN

                IF (digitToRound > 5) THEN

                    SET roundedNumber = ROUND(numberToRound, roundingPrecision);
                ELSE

                    SET roundedNumber = TRUNCATE(numberToRound, roundingPrecision);
                END IF;

            WHEN 'ROUND_HALF_EVEN' THEN

                IF (digitToRound >= 5 AND 
                    digitEvenOdd IN (1,3,5,7,9)
                ) THEN

                    SET roundedNumber = ROUND(numberToRound, roundingPrecision);
                ELSE

                    SET roundedNumber = TRUNCATE(numberToRound, roundingPrecision);
                END IF;

            WHEN 'ROUND_HALF_ODD' THEN

                IF (digitToRound >= 5 AND
                    digitEvenOdd IN (0,2,4,6,8)
                ) THEN

                    SET roundedNumber = ROUND(numberToRound, roundingPrecision);
                ELSE

                    SET roundedNumber = TRUNCATE(numberToRound, roundingPrecision);
                END IF;
        END CASE;

    ELSEIF (roundingPrecision > 0) THEN

        SET roundedNumber = numberToRound;
    END IF;

    RETURN roundedNumber;
END //

随意使用该编码,但不要忘记喜欢我的帖子。谢谢大家的意见和建议。

答案 1 :(得分:1)

可以使用ROUND函数在一行中完成四舍五入:

SELECT ROUND(ROUND({your_input_value}*2,0)/2,1);
  • 第一个ROUND({your_input_value}*2,0)为您提供整数整数的舍入值。
  • 第二个ROUND(... / 2,1)为您提供单个数字结果,而不是更长的结果,并且有更多的零和可能的浮点偏差。

可以创建类似的其他轮次,包括向上,向下或其他乘数,如3,4等。

答案 2 :(得分:1)

MySQL中ROUND()函数中存在一个错误很长一段时间它会返回不一致的结果,具体取决于它是否考虑输入值是否为精确近似数字。至少记录了几个错误(请参阅here以及行为here的MySQL 5.7描述)。

我遇到了MySQL 5.6.22的问题,但从2001年的一些讨论来看,这似乎是非常普遍的。它似乎已经在2018年底的2018年初确定了,但我无法证明哪些版本有效正确,哪些没有。

以下是一种解决方法,无论<input_value>是否被MySQL视为完全近似数字:

SELECT ROUND(CAST(<input_value> AS DECIMAL(10,2)), 1)

如果您需要舍入到更多的圆形位置,请将第二个参数从ROUND()更改为1到您需要的小数位数,将第二个参数更改为DECIMAL()来自{{} 1}}比你需要的小数位数高一个值。例如。您可以使用3位小数:

2

请注意,SELECT ROUND(CAST(<input_value> AS DECIMAL(10,4)), 3) 的第一个参数是数字中的总位数,因此,如果您需要存储较大的值,则可能需要相应地进行调整。有关详细信息,请参阅MySQL manual

答案 3 :(得分:0)

如果在应用@Jonathan函数时遇到错误,则说:

Error 1418: This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable) SQL Statement:...

您应将DETERMINISTIC或其他适用的声明放在BEGIN之前

DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled