Объяснение, почему (7.8 / 39) = .2 не возвращает результаты в предложении where - PullRequest
0 голосов
/ 25 апреля 2020

Итак, я знаю, почему (7.8 / 39) =. 2 не возвращает результаты в предложении where в SQL, тогда как ROUND ((7.8 / 39), 1) =. 2 возвращает результаты, но я не Я знаю, как объяснить это кому-то, с кем я работаю, и я хотел бы предоставить им что-то, что я прочитаю, а затем я скажу им, что это не сработает как часть их предложения where.

Спасибо вам,

Жалал

Ответы [ 2 ]

3 голосов
/ 25 апреля 2020

Это связано с арифметикой с плавающей точкой c. Это может быть трудно объяснить, если вы не просто «получите» это.

С чего мне начать? Целые числа довольно легко представить в битах, которые понимает процессор. Таким образом, 00000101 интерпретируется как 5 - а именно 5 - потому что это 2 ^ 2 + 2 ^ 0.

Однако это не работает для дробных частей чисел. Чтобы решить эту проблему, ученые-компьютерщики изобрели две формы чисел. Одним из них является то, что я лично считаю BCD (двоично-десятичным), но базы данных называют decimal или numeric. Каждый ди git представлен как число. Вам нужно только 4 бита для di git, так что это выглядит так:

0011    0001    1111     0000     1001
   3       1       .        0        9

Это точно соответствует 31.09. Просто продолжайте добавлять биты. Примечание: это концептуально. Точная реализация может отличаться.

Второй метод - экспоненциальная запись. То есть: ххх * 2 ^ гггг, где ххх и ггг - целые числа. Например, 0,25 - это 1 * 2 ^ (- 2). «1» и «-2» могут быть точно представлены.

Это хорошо работает для приближений чисел. Проблема в том, что 0,25 может быть точно представлено. Но 0,24 и 0,26 нельзя. Они заканчивают с некоторыми сложными числами, вовлеченными. То же самое относится и к 0,2 - это число, которое вы пытаетесь представить.

В результате получается, что вы пишете 0,2, и оно представляется как 0,00110011001 (скажем). Но когда вы выполняете вычисления, получается 0,00110011000. Оооо. Этот последний бит изменился, поэтому он действительно больше похож на 0.19997 (ну, на практике немного больше 9). Значения не совсем равны.

Мораль: не используйте равенство на числах с плавающей запятой. Числа могут выглядеть одинаково, но различаются в некотором двоичном двоичном десятичном знаке.

0 голосов
/ 25 апреля 2020

Я пытался использовать свою «Vertica Analyti c База данных v9.3.1-0», так как мои SELECT VERSION() возвращает:

select (7.8/39)=.2 as is_it_true

Возвращает:

is_it_true

true

Чтобы быть уверенным и избежать любых проблем с плавающей запятой, попробуйте привести два операнда равенства к одному и тому же типу:

select (7.8/39)::NUMERIC(5,1) = .2::NUMERIC(5,1)

...