|
Запрос через COM выдаёт 10,68999999 вместо 10,69 | ☑ | ||
---|---|---|---|---|
0
DirecTwiX
23.09.14
✎
11:34
|
Пробовал использовать ВЫРАЗИТЬ КАК ЧИСЛО (15, 2) - результат тот же. Кто-нибудь сталкивался? Как бороться?
1С:Предприятие 8.3 (8.3.5.1119) |
|||
1
ДенисЧ
23.09.14
✎
11:34
|
Это норма.
Округляй при получении. |
|||
2
DirecTwiX
23.09.14
✎
11:37
|
(1) Это беда..
Ладно, спасибо! |
|||
3
vasbur
23.09.14
✎
11:47
|
(1) (2) это float
|
|||
4
stix2010
23.09.14
✎
11:49
|
Выразить Как Строка
|
|||
5
Serginio1
23.09.14
✎
11:50
|
Вообще странно, так как Decimal прекрасно передается через COM.
Передавай как строку |
|||
6
DirecTwiX
23.09.14
✎
11:53
|
Вариант. Спасибо!
Я пытался... :@
Правда Стр[КлЗн.Ключ] = Окр(Стр[КлЗн.Ключ], Разрядность); Всё равно не работает -.- |
|||
7
DirecTwiX
23.09.14
✎
11:56
|
|
|||
8
bolobol
23.09.14
✎
11:58
|
Выразить-то надо как число 15,2!
|
|||
9
DirecTwiX
23.09.14
✎
12:07
|
(8) В (0) писал, что уже пробовал..
Тем не менее, победа :) Выразить (СУММА(ВТ.ЗП)*100 как Число(17)) |
|||
10
Мыш
23.09.14
✎
12:07
|
(0) Это известная трабла. Проблема не в 1С. Проблема в COM )
|
|||
11
Serginio1
23.09.14
✎
12:16
|
(10) Проблема в 1С ибо Decimal прекрасно передается через COM http://rsdn.ru/article/com/varsafearr.xml#EZF
|
|||
12
Мыш
23.09.14
✎
12:30
|
(11) Борис, ты не прав ) Если сом отдает не децимал, а вариант, то 1С тут ничо не может сделать.
|
|||
13
Serginio1
23.09.14
✎
12:41
|
(12) Сом всегда передает Вариант. А вот внутри варианта прекрасно уживается Децимал. Я тебе ссылку для чего приводил?
А вот 1С в вариант устанавливает double |
|||
14
Torquader
23.09.14
✎
15:37
|
(13) Внутри Variant Decimal живёт с огромными костылями, так как стандартом не является, а просто занимает всю структуру Variant.
Другое дело, что Currency (то есть восемь байт на целое число, сдвинутое на четыре разряда) прекрасно живёт в OLE и никогда нигде не теряется. Но, стандарт общения между программами по OLE предписывает использовать Double для чисел с плавающей или фиксированной точкой и Long для целых чисел. В том же Excel мы имеем такие же грабли, только ещё и значение в ячейке может быть "округлено". P.S. можно умножить на 100 и выразить как целое число - по идее, должен передать как целое, но если оно за пределы Long вылезет, то опять же - будет Double, так как Decimal или Currency нужно указывать специально (1С-то этого не умеет). |
|||
15
Torquader
23.09.14
✎
15:39
|
+
В VbScript, например, можно полученный результат преобразовать CCur(Value) и мы получим значение без округления. Конечно, есть вероятность, что там что-то потеряется (если передавать номер счёта как число, то Currency просто уже не хватит), но намного меньше. |
|||
16
Torquader
23.09.14
✎
15:41
|
+
У меня спасало Ole.String(Запрос.ИмяПоля) - преобразование в строку шло ещё до начала работы с OLE, но 1С настолько криво преобразует число в строку. |
|||
17
DmitrO
23.09.14
✎
15:43
|
(14) "живёт с огромными костылями"???
VT_DECIMAL не является стандартом??? хренова гора функций decimal арифметики и преобразований в/из decimal расположенных в системных OLE библиотеках windows это случайность??? |
|||
18
Torquader
23.09.14
✎
16:36
|
Чего-то посмотрел в исходники:
VariantToInt32, VariantToInt64, VariantToDouble, VariantToGuid чего-то там нет VariantToDecimal собственно как и VariantToCurrency. Просто, если бы в 1С делали правильно, то могли бы вообще определить свой тип данных, так как они используют внутренние представления чисел более сложные, чем Variant и передавать их по OLE спокойно через структуры, но они пошли по простому пути, а самый простой путь - это Double, так как вся работа с ним выполняется сопроцессором (в отличие от Decimal, для которого нужна специальная библиотека). |
|||
19
Torquader
23.09.14
✎
16:41
|
И, самое главное, Microsoft Script Control и VbScript не поддерживают Decimal вообще.
И вообще, прямым языком написано, если вы перемножаете два целых числа, то результатом может быть значение типа Double - почему-то не Int64 и не Decimal или Currency, а именно Double. Вполне вероятно, что выполняя внутренние преобразования своих чисел к переменной Variant 1С использует стандартные библиотеки, которые именно так и работают. |
|||
20
DmitrO
23.09.14
✎
16:47
|
||||
21
Serginio1
23.09.14
✎
16:48
|
(14) Живет без костылей http://rsdn.ru/article/com/varsafearr.xml#EZF
1С 8.2 прекрасно понимает Decimal. Специально делал тесты. |
|||
22
DmitrO
23.09.14
✎
17:07
|
8ка нормально принимает все типы VARIANT, в том числе и VT_DECIMAL (можно проверить например через ADODB), и даже VT_UNKNOWN.
Однако у них плохо написан COMConnector (V8.Application, V8C.Application тоже) дело в том что они свои числа выдают как VT_R8 (double), если число имеет дробную часть. А сделано это вероятно для того чтобы с этими COM серверами можно было работать из 7ки, ибо она не принимает VT_DECIMAL. |
|||
23
DmitrO
23.09.14
✎
17:15
|
Внутренние данные чисел 1C (и 7ой и 8ой) отличаются от данных хранимых в VARIANT типа VT_DECIMAL, они хранятся по другому, однако наиболее близкое представление это именно VT_DECIMAL, числа 1С только могут быть больше.
Поэтому арифметика (имею в виду функции) у них собственная. |
|||
24
Fragster
гуру
23.09.14
✎
17:18
|
В запросе использовать функцию Представление, тогда в результате будет строка, причем которую функция "число()" должна вроде как сожрать
|
|||
25
DmitrO
23.09.14
✎
17:20
|
(24)представление будет зависеть от локализации сеанса
|
|||
26
DmitrO
23.09.14
✎
17:25
|
Им (1С) надо в COMConnector (в свои COM сервера) дописать примерно такое свойство ReturnNumericsAs со значениями {Real, Decimal}, но это же такие пустяки.. :)
|
|||
27
Serginio1
23.09.14
✎
18:04
|
(26) Что я например и сделал для доступа к классам .Net
Правда я перевожу все в строку для инвариантного языка .ToString(CultureInfo.InvariantCulture); А в 7 ке таких типов куча if (ЭтоСемерка) { Тип = obj.GetType(); if (Тип == typeof(System.Decimal)) return ((Decimal)obj).ToString(CultureInfo.InvariantCulture); if (Тип.IsPrimitive) { if ((Тип == typeof(System.Int64) || Тип == typeof(System.UInt32) || Тип == typeof(System.UInt64) || Тип == typeof(System.UInt16) || Тип == typeof(System.SByte))) obj = Convert.ChangeType(obj, typeof(string), CultureInfo.InvariantCulture); } |
|||
28
Torquader
23.09.14
✎
18:38
|
(27) Собственно говоря, любое число можно вообще в виде 16-ричной строки записать, как Dump памяти.
Просто на это будет тратится машинное время. И, самое печальное, что ни "осёл" ни VbScript корректно с Decimal не работают. (22) А точно 1С понимает именно Decimal, а не просто переводит его в Double сразу при получении, например, VariantChangeType прекрасно может преобразовывать типы, про которые получатель ничего не знает - нужно лишь чтобы система умела выполнить преобразование. |
|||
29
Serginio1
23.09.14
✎
18:49
|
(28) Да. Получает то она вариант с Decimal.
Я специально проверял типы public object ПолучитьМассивТипов() { var list = new List<object>(); list.Add("System.String"); list.Add(AutoWrap.ОбернутьОбъект(DateTime.Now)); list.Add(AutoWrap.ОбернутьОбъект(true)); list.Add(AutoWrap.ОбернутьОбъект((System.Byte)45)); list.Add(AutoWrap.ОбернутьОбъект((System.Decimal)48.789)); list.Add(AutoWrap.ОбернутьОбъект((System.Double)51.51)); list.Add(AutoWrap.ОбернутьОбъект((System.Single)11.11)); list.Add(AutoWrap.ОбернутьОбъект((System.Int32)11)); list.Add(AutoWrap.ОбернутьОбъект((System.Int64)789988778899)); list.Add(AutoWrap.ОбернутьОбъект((System.SByte)45)); list.Add(AutoWrap.ОбернутьОбъект((System.Int16)66)); list.Add(AutoWrap.ОбернутьОбъект((System.UInt32)77)); list.Add(AutoWrap.ОбернутьОбъект((System.UInt64)88888888888888)); list.Add(AutoWrap.ОбернутьОбъект((System.UInt16)102)); return new AutoWrap(list); } |
|||
30
Serginio1
23.09.14
✎
18:49
|
И выдавал именно те значения которые и передавались
|
|||
31
Chai Nic
23.09.14
✎
19:03
|
А в чем проблема.. обертывай таблицу значений результата запроса в строку и передавай через COM.. Через комбинацию ЗначениеВСтрокуВнутр/ЗначениеИзСтрокиВнутр.. Костыли, но достаточно удобные.
|
|||
32
Serginio1
24.09.14
✎
10:09
|
(28) Кстати есть поддержка в
Синтаксис: Новый COMSafeArray(<ТипЭлемента>, <<разм0>,...,<размN-1>>) Параметры: <ТипЭлемента> (обязательный) Тип: Строка. Определяет тип элемента COMSafeArray. Тип элемента задается строкой и может принимать одно из следующих значений: VT_I1 - знаковое целое 1 байт; VT_I2 - знаковое целое 2 байта; VT_I4 - знаковое целое 4 байта; VT_I8 - знаковое целое 8 байт; VT_INT - знаковое целое; VT_UI1 - беззнаковое целое 1 байт; VT_UI2 - беззнаковое целое 2 байта; VT_UI4 - беззнаковое целое 4 байта; VT_UI8 - беззнаковое целое 8 байт; VT_UINT - беззнаковое целое; VT_R4 - действительное число 4 байта; VT_R8 - действительное число 8 байт; VT_DECIMAL - десятичное число с фиксированной точкой 12 байт; VT_CY - значение денежного типа; VT_DATE - значение типа дата; VT_BSTR - значение типа строка; VT_DISPATCH - указатель на интерфейс IDispatch; VT_ERROR - код ошибки; VT_BOOL - значение логического типа; VT_UNKNOWN - указатель на интерфейс IUnknown; VT_VARIANT - вариантный тип. |
|||
33
Torquader
24.09.14
✎
10:14
|
И ещё вопрос - как число хранится в SQL-сервере ?
Просто, есть вероятность, что округление происходит как раз в момент получения данных из SQL-сервера, а не при передаче по OLE. Не стоит забывать, что при выводе числа дробная часть по умолчанию, округляется до 6 знаков. |
|||
34
Serginio1
24.09.14
✎
10:40
|
||||
35
Torquader
24.09.14
✎
23:48
|
(34) Так как раз и написано, что 17 знаков - то есть Double и округление - так что есть подозрение, что именно на этом моменте знаки и теряются.
decimal и numeric - это слова для описания чисел, а не типы. |
|||
36
Serginio1
24.09.14
✎
23:56
|
(35) Это типы. Там кстати написано
When converting float or real values to decimal or numeric, the decimal value will never have more than 17 decimals. decimal [ (p[ ,s] )] и numeric[ (p[ ,s] )] Числа с фиксированной точностью и масштабом. При использовании максимальной точности числа могут принимать значения в диапазоне от -10^38+1 до 10^38-1. Синонимами по стандарту ISO для decimal являются dec и dec(p, s). numeric функционально эквивалентно decimal. p (точность) Максимальное количество десятичных разрядов числа (как слева, так и справа от десятичной запятой), которые будут храниться. Точность должна быть значением в диапазоне от 1 до максимум 38. Точность по умолчанию составляет 18. s (масштаб) Максимальное количество хранимых десятичных разрядов числа справа от десятичной запятой. Это число отнимается от p для определения максимального количества цифр слева от десятичной запятой. Максимальное количество десятичных разрядов числа справа от десятичной запятой. Масштаб может принимать значение от 0 до p. Масштаб может быть указан только совместно с точностью. По умолчанию масштаб принимает значение 0; поэтому 0 <= s <= p. Максимальный размер хранилища зависит от точности. |
|||
37
Cube
25.09.14
✎
05:23
|
||||
38
Torquader
26.09.14
✎
20:58
|
Кстати, а если попробовать задать числу 20 целых знаков, то есть (20,2), чтобы оно гарантированно в Double не влезла.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |