Округление десятичных дробей

Qwest-fx

Профессор
Регистрация
3 Апр 2007
Сообщения
134
Реакции
41
PHP:
-- --------------------------------------------------------
-- Хост:                         127.0.0.1
-- Версия сервера:               5.5.36-MariaDB - MariaDB Server
-- ОС Сервера:                   Linux
-- HeidiSQL Версия:              8.3.0.4694
-- --------------------------------------------------------

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;

-- Дамп структуры базы данных test_float
CREATE DATABASE IF NOT EXISTS `test_float` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `test_float`;


-- Дамп структуры для таблица test_float.test
CREATE TABLE IF NOT EXISTS `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` float NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

-- Дамп данных таблицы test_float.test: ~10 rows (приблизительно)
/*!40000 ALTER TABLE `test` DISABLE KEYS */;
INSERT INTO `test` (`id`, `a`) VALUES
    (1, 0.001),
    (2, 0.002),
    (3, 0.003),
    (4, 0.004),
    (5, 0.005),
    (6, 0.006),
    (7, 0.007),
    (8, 0.008),
    (9, 0.009),
    (10, 0.015);
/*!40000 ALTER TABLE `test` ENABLE KEYS */;
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

Пример запроса с округлением
PHP:
select *, round(`a`,2) as 'round' from test
Результат
20150518_193623.png


Второй пример запроса с использованием округления
PHP:
select round(0.015,2)
20150518_193645.png


Знающие люди объясните в чем разница?
Как округлять числа до 2х знаков по правилам математического округления?
 
Последнее редактирование:
С округлением флоатов не только в mysql проблемы.
Возможно вот этот костыль прояснит немного ситуацию:
Код:
select *, round(`a`, 10), round(round(`a`, 3), 2) as 'round' from test


просто "некоторые" числа в BIN-e имеют вид бесконечной дроби.
Скажем, например попадется десятичное число xxx.5, которое при переводе DEC->BIN даст вам xxx.4999999999(9) в десятичном эквиваленте.
Ну примерно также как невозможно выразить одну треть в виде конечной десятичной дроби.
Правильно использовать не float или double, а decimal, или numeric, с указанием нужной точности.
Для просмотра ссылки Войди или Зарегистрируйся
 
Попробуйте
select cast(a as decimal(10,2));
 
1398793614-clip-6kb.png

1398793774-clip-2kb.png

Так и в чём разница?
Даже так
select cast('0.015' as decimal(10,2)) as 'cast'
 
Я почитал, погонял тесты, и понял!

ALTER TABLE `test` CHANGE `a` `a` DECIMAL (5,3) NOT NULL;
 
Назад
Сверху