Могут ли типы FLOAT быть усечены в хранимых функциях MySQL? - PullRequest
0 голосов
/ 05 июня 2019

Я новичок в MySQL и сохраненных функциях, поэтому я прошу прощения, если этот вопрос кажется элементарным.

Я пишу хранимую функцию, в которой мне нужно обрезать число с плавающей точкой до определенного количества десятичных разрядов. Насколько я понимаю, встроенная функция TRUNCATE должна сделать это для меня; однако результат, который я получаю, не усекается вообще. Единственное заметное изменение заключается в том, что некоторые цифры после предполагаемой точки усечения отличаются от исходного числа.

Я попытался поэкспериментировать с функцией усечения самостоятельно с теми же числами (необработанными), т.е. SELECT TRUNCATE (0.00123456, 5) AS «Пример», и это работает так, как ожидалось. У меня есть ощущение, что моя проблема в хранимой функции связана с типом float, используемым в качестве параметра в функции усечения.

Я должен отметить, что причина, по которой я обрезаю это число в первую очередь, заключается в том, что функция округления не может обрезать количество десятичных знаков, как ожидалось. Я объясню это более подробно (и с помощью фактической функции в качестве примера) здесь: Каков правильный синтаксис предложения if для хранимой функции MySQL? , но для ясности я включил ниже урезанный код ниже

CREATE FUNCTION 'sfround'(number FLOAT, sigFigs INT) RETURNS FLOAT
DETERMINISTIC
BEGIN

DECLARE nonTruncated FLOAT;
DECLARE truncated FLOAT;
DECLARE decimalsKept INT;

#some not relevant code in the middle

SET nonTruncated = ROUND(number, sigFigs-1-FLOOR(LOG10(ABS(number))));
SET truncated = TRUNCATE(nonTruncated, decimalsKept);

RETURN truncated;

END$$

Когда мои входные данные являются любыми числами от 1 до -1 (исключая 0, потому что я включил крайний регистр, чтобы иметь дело с 0), эта функция возвращает число, которое является правильным вплоть до предполагаемой точки усечения, после чего, казалось бы, не имеет отношения появляется список номеров (одинаковые номера при каждом вызове функции).

Ex. sfround (0,00123456, 5) дает 0,0012344999704509974.

Есть ли какая-то причина, по которой усечение несовместимо с типами FLOAT? Или я что-то здесь упускаю?

1 Ответ

0 голосов
/ 05 июня 2019

Да, они несовместимы.

FLOAT хранит данные в двоичном формате IEEE-754, который хранится в базе 2. Фракция 10 базы не подходит точно.Таким образом, ваша функция получает что-то около 0,0012345 для усечения, но FLOAT не может держать это точно, поэтому вы получите требуемое число.См. Множество ответов здесь и в других местах, особенно Что должен знать каждый компьютерный специалист об арифметике с плавающей запятой , чтобы узнать, как число с плавающей запятой в формате IEEE представляется в виде.

Есливы хотите иметь точное количество десятичных знаков, которые вам нужно использовать DECIMAL тип

...