powered by simpleCommunicator - 2.0.39     © 2025 Programmizd 02
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / Неверный вывод цифр при импорте из SQL Server'а
25 сообщений из 33, страница 1 из 2
Неверный вывод цифр при импорте из SQL Server'а
    #38920464
MrVoid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет!
Имеется такая проблема. Есть таблица в SQL Server'е, в которой есть поле с типом данных "float(24)". Вывожу эту таблицу в Excel через Range.CopyFromRecordset. В этом поле есть значение "0,22". Вот результаты тестов:

1) При выводе на лист Range.CopyFromRecordset преобразует "0,22" в "0,219999998807907".
2) При выводе в "умную таблицу" значение корректно выводится - "0,22".
3) Если поменять тип данных на float(25), то есть уже 8 байт, то Range.CopyFromRecordset корректно выводит на лист "0,22".

Итак, чтобы корректно вывести "0,22", мне нужно увеличить размер типа данных аж в два раза, что не очень-то политкорректно.
Умная таблица тоже разочаровала: если перед записью данных очистить таблицу, то DataBodyRange будет Nothing, и из-за этого CopyFromRecordset выдаст оишбку. Чтобы этого не было, надо искусственно добавить туда что-то (хоть единичку). Это уже какие-то грязные хаки.
Собственно, вопрос - как заставить Эксель, чтобы он корректно выводил float(24) на лист? :)
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38920466
cast,
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MrVoid,

float - "в принципе" неточный, "приближённый" тип данных, и, раз его "неточность" создаёт проблему, то скорее всего выбран в таблице ошибочно.
В МС СКЛ есть точные типы для хранения дробных значений - money, decimal.
Так что самое правильное было бы изменить тип.
Если это сделать нельзя, то можно приводить к другому типу в запросе-источнике рекордсета
cast(f as decimal(18,2)) или просто round(f, 2)
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38920475
MrVoid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
castfloat - "в принципе" неточный, "приближённый" тип данных
А почему тогда с float(25) нет проблем?
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38920480
cast,
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MrVoidcastfloat - "в принципе" неточный, "приближённый" тип данных
А почему тогда с float(25) нет проблем?
Вот "захочешь" 3-ю, 4-ую, ...., 8-ую точную цифру, после запятой - появятся проблемы и с float(25) :)
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38920483
MrVoid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Decimal юзать тоже как-то не очень охота использовать ради того, чтобы Экселю понравилось.
Может, вообще захреначить varchar - и головушку не забивать.
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38920486
MrVoid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну ладно... А почему умная таблица всё корректно сделала?
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38920617
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MrVoidDecimal юзать тоже как-то не очень охота использовать ради того, чтобы Экселю понравилось.
Может, вообще захреначить varchar - и головушку не забивать. какого рода данные ты там хранишь? Если деньги с точностью до копеек или количество с точностью до трех знаков после запятой, то как раз стоит подумать о смене типа
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38921743
MrVoid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreymx,

Данные - не деньги. Но после запятой будет не более двух знаков - точно.
Выгружал данные из скуля в Access - всё ОК. Выходит корректно 0,22. Использовать такие хаки как использование decimal или float(25) не совсем корректно ради того, чтобы в Эксель выгрузилось нормально. Преобразовывать данные на лету - тоже не хочется (тем более, что полей очень много). Это надо писать портянку из 30-40 столбцов ради того, чтобы преобразовать пару столбцов.
Можно вместо CopyFromRecordset "вручную" перенести данные через While..Wend, но тут всё равно надо знать, какие столбцы преобразовывать, да и получается намного медленне.
В общем, зашёл в тупик...
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38921776
Казанский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
[quot MrVoidпосле запятой будет не более двух знаков - точно[/quot]Округлите до 2 знаков после выгрузки на лист. Без цикла
Код: vbnet
1.
myRange.Value = Application.Round(myRange, 2)
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38921868
MrVoid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да все эти хаки я знаю. Можно и хранимую процедуру написать, чтобы всё красиво было. Но это всё ради капризов экселя. :(
Спасибо всем! Поведение Экселя осталось невыясненным.
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922013
cast,
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MrVoidДа все эти хаки я знаю. Можно и хранимую процедуру написать, чтобы всё красиво было. Но это всё ради капризов экселя. :(
Спасибо всем! Поведение Экселя осталось невыясненным. тьху! Что ж ты никак не поймешь-то?!
Не при чём тут Эксель!
Там, в таблице, реально хранится 0,219999998807907, хотя сохраняли 0,22!
А происходит так, потому что в експ.форме, в двоичной системе счисления, десятичное 0.22 представляется бесконечной дробью!
Поиграйся http://math.semestr.ru/inf/ieee754.php
Представление двоичного числа с плавающей точкой в экспоненциальном нормализованном виде.
Для этого переведем число в двоичное представление.
Для перевода дробной части числа последовательно умножаем дробную часть на основание 2. В результате каждый раз записываем целую часть произведения.
0.22*2 = 0.44
(целая часть 0)
0.44*2 = 0.88
(целая часть 0)
0.88*2 = 1.76
(целая часть 1)
0.76*2 = 1.52
(целая часть 1)
0.52*2 = 1.04
(целая часть 1)
0.04*2 = 0.08
(целая часть 0)
0.08*2 = 0.16
(целая часть 0)
0.16*2 = 0.32
(целая часть 0)
0.32*2 = 0.64
(целая часть 0)
0.64*2 = 1.28
(целая часть 1)
0.28*2 = 0.56
(целая часть 0)
0.56*2 = 1.12
(целая часть 1)
0.12*2 = 0.24
(целая часть 0)
0.24*2 = 0.48
(целая часть 0)
0.48*2 = 0.96
(целая часть 0)
0.96*2 = 1.92
(целая часть 1)
0.92*2 = 1.84
(целая часть 1)
0.84*2 = 1.68
(целая часть 1)
0.68*2 = 1.36
(целая часть 1)
0.36*2 = 0.72
(целая часть 0)
0.72*2 = 1.44
(целая часть 1)
0.44*2 = 0.88
(целая часть 0)
0.88*2 = 1.76
(целая часть 1)
Получаем число в 2-ой системе счисления: 00111000010100011110101
0.22 = 00111000010100011110101 2

Сдвинем число на 3 разрядов вправо. В результате мы получили основные составляющие экспоненциального нормализованного двоичного числа:
Мантисса M=1.11000010100011110101000
Экспонента exp2=-3
Преобразование двоичного нормализованного числа в 32 битный формат IEEE 754.
Первый бит отводится для обозначения знака числа. Поскольку число положительное, то первый бит равен 0
Следующие 8 бит (с 2-го по 9-й) отведены под экспоненту.
Для определения знака экспоненты, чтобы не вводить ещё один бит знака, добавляют смещение к экспоненте в половину байта +127. Таким образом, наша экспонента: -3 + 127 = 124
Переведем экспоненту в двоичное представление.
124 = 11111002
Оставшиеся 23 бита отводят для мантиссы. У нормализованной двоичной мантиссы первый бит всегда равен 1, так как число лежит в диапазоне 1 ≤ M < 2. Для экономии, единицу не записывают, а записывают только остаток от мантиссы: 11000010100011110101000
Для перевода необходимо умножить разряд числа на соответствующую ему степень разряда.
11000010100011110101000 = 222*1 + 221*1 + 220*0 + 219*0 + 218*0 + 217*0 + 216*1 + 215*0 + 214*1 + 213*0 + 212*0 + 211*0 + 210*1 + 29*1 + 28*1 + 27*1 + 26*0 + 25*1 + 24*0 + 23*1 + 22*0 + 21*0 + 20*0 = 4194304 + 2097152 + 0 + 0 + 0 + 0 + 65536 + 0 + 16384 + 0 + 0 + 0 + 1024 + 512 + 256 + 128 + 0 + 32 + 0 + 8 + 0 + 0 + 0 = 6375336
В десятичном коде мантисса выражается числом 6375336
В результате число 0.22 представленное в IEEE 754 c одинарной точностью равно 0111110011000010100011110101000.
Переведем в шестнадцатеричное представление.
Разделим исходный код на группы по 4 разряда.
01111100110000101000111101010002 = 0011 1110 0110 0001 0100 0111 1010 1000 2
Получаем число:
0011 1110 0110 0001 0100 0111 1010 1000 2 = 3E6147A816
Проверим правильность перевода.
Чтобы записать число в стандарте IEEE 754 или восстановить его, необходимо знать три параметра:
S - бит знака (31-й бит).
E - смещенная экспонента (30-23 биты).
M - остаток от мантиссы (22-0 биты).
Формула для получения десятичного числа из числа IEEE754 одинарной точности:
F = (-1)S2(E-127)(1+M/223)
F = (-1)02(124-127)(1+6375336/223) = 0.125*1.75999927 = 0.21999990

Итого:
если нужно точное представление дес.дробей, нужно использовать
или decimal - в котором хранится двоичное представление последовательности десятичных цифр
или money - в котором хранится умноженное на 10000 исх.десятичное число, как двоичное целое число
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922154
MrVoid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
castтьху! Что ж ты никак не поймешь-то?!
Не при чём тут Эксель!

А почему тогда Access НЕ показывает эту бесконечную дробь? И заметьте, что я не провожу каких-либо математических операций с этой цифрой.
Провёл такой тест. В скуле дёрнул эти 0,22 и сравнил с 0,22. Результат - True. Они равны. Следовательно, Эксель делает какие-то левые преобразования на лету.
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922184
f
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Приведи код сравнения.
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922193
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MrVoidА почему тогда Access НЕ показывает эту бесконечную дробь?потому что существует форматирование при выводе
MrVoidПровёл такой тест. В скуле дёрнул эти 0,22 и сравнил с 0,22. Результат - Trueпри сравнении операнды приводятся к одному типу (неявно в данном случае), поэтому они и равны.

Еще раз, в экспоненциальной форме хранятся принципиально неточные числа (они хранятся с определенной заданной точностью), для точных чисел есть неэкпоненциальные типы.

Если очень хочется увидеть своими глазами, можно провести эксперимент - сложить в цикле это число N раз. Отдельно умножить это число на N. И сравнить результат. Вот наглядный пример для экселя.
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922200
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MrVoidПровёл такой тест. В скуле дёрнул эти 0,22 и сравнил с 0,22. Результат - Trueвот так попробуй
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
Dim k As Single, i As Integer, sum1 As Single, sum2 As Single
k = 0.22

For i = 1 To 10000
  sum1 = sum1 + k
Next
sum2 = k * 10000
MsgBox sum1 & vbCr & sum2
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922204
MrVoid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProMrVoidА почему тогда Access НЕ показывает эту бесконечную дробь?потому что существует форматирование при выводе

Щито? Причём тут форматирование? Эксель преобразовывает , а не форматирует.

Вот скрипт в скуле:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
declare @n real, @digit real = 0.22;

select @n = Объём
from dbo.УВК
where НомерЗадачи = 21;

if @n = @digit 
	print 'Numbers ARE equal'
else 
	print 'Numbers ARE NOT equal';

/* Ответ - "Numbers ARE equal" */
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922207
f
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProMrVoidПровёл такой тест. В скуле дёрнул эти 0,22 и сравнил с 0,22. Результат - True
К тому же в скуле не бывает True.
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922208
MrVoid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProMrVoidПровёл такой тест. В скуле дёрнул эти 0,22 и сравнил с 0,22. Результат - Trueвот так попробуй
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
Dim k As Single, i As Integer, sum1 As Single, sum2 As Single
k = 0.22

For i = 1 To 10000
  sum1 = sum1 + k
Next
sum2 = k * 10000
MsgBox sum1 & vbCr & sum2



Причём тут математика? Я *НЕ делаю* арифмитеческих действий. Ондастанд?
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922214
MrVoid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FК тому же в скуле не бывает True.
Имелось ввиду, что они одинаковы. Не надо умничать. :)
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922227
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MrVoidПричём тут математика? Я *НЕ делаю* арифмитеческих действий. Ондастанд?А в чем у тебя тогда проблема? Ты сомневаешься, что число хранится в неточном виде - я продемонстрировал, как это увидеть, можно то же самое написать на TSQL. Ты не понимаешь, почему два одинаковых числа адекватно сравниваются? Я объяснил (или не андестенд?)

Ты путаешь способ форматирования чисел при выводе и способ хранения, поэтому не понимаешь то, что видишь своими глазами.
MrVoidЭксель преобразовывает , а не форматирует.Эксель ничего в данном случае не преобразовывает
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922232
f
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MrVoidFК тому же в скуле не бывает True.
Имелось ввиду, что они одинаковы. Не надо умничать. :)
Тролль детектид.
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922241
MrVoid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
@Shocker.Pro
То есть скуль меня намахивает, когда показывает, что он хранит 0,22, а на самом деле - "0,219999998807907"? А Access тогда что делает, что корректно выводит 0,22?
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922245
MrVoid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FТролль детектид.
Это ты тролль.
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922259
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MrVoid@Shocker.Pro
То есть скуль меня намахивает, когда показывает, что он хранит 0,22, а на самом деле - "0,219999998807907"? наконец дошло

Чтобы в этом убедиться, возьми его и просуммируй в цикле, как я показывал. Число может быть не совсем это (все будет зависеть от точности, тут похоже на одинарную точность), но оно не 0,22 ровно. Ровно будет, если будешь использовать decimal или money

MrVoidА Access тогда что делает, что корректно выводит 0,22? форматирует при выводе, для твоего удобства
...
Рейтинг: 0 / 0
Неверный вывод цифр при импорте из SQL Server'а
    #38922267
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MrVoidТо есть скуль меня намахивает, когда показывает, что он хранит 0,22, а на самом деле - "0,219999998807907"на самом деле, он хранит нолики и единички. Хранить их можно по-разному. Чтобы не писать тебе тут лекцию, почитай про двоично-десятичные преобразования и формат и операции с плавающей точкой (если интересно, конечно)
...
Рейтинг: 0 / 0
25 сообщений из 33, страница 1 из 2
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / Неверный вывод цифр при импорте из SQL Server'а
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]