parserALT
Страницы форума: ← Назад | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 600 | Дальше →

Проблемы с double

#1nkostya
27.11.11 14:50 / 14:51
www.parser.ru → | ответить → | в избранное →

Проблемы с double

На Mac, 64 битный parser вижу следующие проблемы:

1. Код
$double[12300.24]
$result[$double]

Возвращает 12300.24

2. Код

$double(12300.24)
$result[$double]

Возвращает 12300.2

3. Код

$double(12300.24)
$result[^double.format[%f]]

Возвращает 12300.240000

4. Код

$double[12300.66]
$double[^double.double[]]
$result[$double]

Возвращает 12300.7

5. Код

$double[12300.66]
$double[^double.double[]]
$result[^double.format[%f]]

Возвращает 12300.700000

Итого мы получаем, что при преобразовании числа в double (см. 4 и 5) мы теряем правильное значение. Это ошибка или так задумывалось?
#2nkostya
→ nkostya [#1] | 27.11.11 15:00
www.parser.ru → | ответить → | в избранное →

Уточнение

Если число не очень большое, например, 5000 - порядок не теряется.
А если уже 15000, то есть потеря.
#3Vint
→ nkostya [#1] | 27.11.11 15:12
www.parser.ru → | ответить → | в избранное →
Так надо во всех местах, где переменной присваивается преобразованное число, писать круглые скобки:
$double[12300.66]
$double(^double.double[])
$result[^double.format[%f]]

Вернёт 12300.66
#4nkostya
→ Vint [#3] | 27.11.11 16:14 / 16:15
www.parser.ru → | ответить → | в избранное →
Использовать круглые скобки абсолютно везде не всегда возможно.

На мой взгляд это не совсем логично поведение преобразования. Т.е. я сначала принудительно преобразую переменную в double, а потом она преобразуется в строку с округлением. Почему парсер решает что мне нужно ее округлить?
#5G_Z
→ nkostya [#4] | 27.11.11 16:17
www.parser.ru → | ответить → | в избранное →
Почему парсер решает что мне нужно ее округлить?

Видимо потому что не задан формат при преобразовании к строке.
#6Sumo
→ nkostya [#4] | 27.11.11 16:23
www.parser.ru → | ответить → | в избранное →

В каком конкретно случае вы не можете использовать круглые скобки?

#7nkostya
→ G_Z [#5] | 27.11.11 16:36
www.parser.ru → | ответить → | в избранное →
Так не задан - значит не менять, а не преобразовать к странному формату.

Странный формат - если 5000.66, то получу при преобразовании к строке 5000.66, а если 15000.66, то получу 15000.7

Каким образом парсер так решает?

Решение с ^var.format[...] понятно, но в моем случае не применимо.
#8nkostya
→ Sumo [#6] | 27.11.11 16:38 / 16:38
www.parser.ru → | ответить → | в избранное →
У меня есть некий класс DBField, который хранит тип переменной и у него есть метод
^field.init[$value], который возвращает значение. Т.к. он универсален и используется как

^fields.foreach[alias;field]{
	$attributes.[$alias][^field.init[$value]]
}


То при работе с double я получаю искажения данных.
#9Sumo
→ nkostya [#7] | 27.11.11 16:40
www.parser.ru → | ответить → | в избранное →

Так вы почитайте в доке про double.format - там все описано....

Если не задавать предобразование, то парсер неявно использует %g, что и приводит к кажущимся проблемам. Если хотите предсказуемого результата, то используйте круглые скобки. [Ну и почитать про то как работают числа с плавающей точкой не помешает — я вам раньше давал ссылку на википедию.]
#10Sumo
→ nkostya [#8] | 27.11.11 16:42
www.parser.ru → | ответить → | в избранное →

$attributes.[$alias][^field.init{$value}]...

... а внутри метода используйте правильные скобки в зависимости от типа.
#11nkostya
→ Sumo [#9] | 27.11.11 16:44
www.parser.ru → | ответить → | в избранное →

%g в Приложении 2 не описан и его использование приводит к ошибке, где можно посмотреть?

#12nkostya
→ Sumo [#10] | 27.11.11 16:49
www.parser.ru → | ответить → | в избранное →
Если я правильно понимаю, то в $attributes.[$alias] идут квадратные скобки и оно при присвоении преобразуется в строку?
#13nkostya
→ Sumo [#10] | 27.11.11 17:05
www.parser.ru → | ответить → | в избранное →

Меня интересуют правильные значения в $attributes

#14G_Z
→ nkostya [#12] | 27.11.11 18:27
www.parser.ru → | ответить → | в избранное →
В примере Sumo там будет объект field.
Как объект реализует хранение значений внутри себя — его личное дело.
И вы на это можете влиять напрямую, написав нужную логику хранения.
#15nkostya
→ G_Z [#14] | 27.11.11 19:16
www.parser.ru → | ответить → | в избранное →

У меня немного иначе

DBField хранит только мета информацию о свойстве.
^field.init[$value] - возвращает значение свойства (в типах парсера) полученное из $value. И тип он хранит в объекте DBField, поэтому проблемы с преобразованием не возникает. А вот с дальнейшим присвоением уже и возникает потеря значений.

Из-за логики преобразований парсером из double в строку пришлось преобразовывать в double, форматировать в строку и возвращать строку.

Как понимаю, другого решения не возможно на текущий момент.
#16G_Z
→ nkostya [#15] | 27.11.11 19:45
www.parser.ru → | ответить → | в избранное →
^switch[$type]{
	^case[double;int]{
		$self.value($value)
	}
	^case[DEFAULT]{
		$self.value[$value]
	}
}
#17Misha v.3
→ nkostya [#1] | 28.11.11 01:16 / 01:28
www.parser.ru → | ответить → | в избранное →

«Класс int2str [kb: как аккуратно работать с числами с плавающей точкой]»

double -- это штука чуть более хитрая, чем вы её себе представляете, судя по этому:

Странный формат - если 5000.66, то получу при преобразовании к строке 5000.66, а если 15000.66, то получу 15000.7

Каким образом парсер так решает?


задание double в виде $var(1.23) -- это лишь частный случай. есть ещё такой способ задания: $var(1/3)
а посре прочтения сообщения PAF-а вы, я надеюсь, поймёте, что после выполнения $f(123.86-123) при выводе полученного double без округления будет выведено совсем не "0.86"

т.е. выводить double-ы без округления нельзя.

а до кучи и другие "полезности"
#18nkostya
→ Misha v.3 [#17] | 28.11.11 08:50
www.parser.ru → | ответить → | в избранное →

Не правильно поняли мое видение проблемы

Проблема возникает не в том, что я забываю привести double к нужному формату, а в:

1. Изначально я знаю тип переменной
2. По ходу кода у меня есть $value и я уже не знаю (и с первого взгляда мне это не важно) тип переменной.
3. Но т.к. я делаю присвоение переменной через [] всегда, то получается что я теряю значение.

Т.е. получается, что если у меня есть $value и я не знаю что это и какие скобки ставить, то при вызове какого-нибудь метода или присвоения другой переменной я теряю ее тип.

^switch[$type]{
^case[double]{
	$value(^sData.double[])
}
^case[int]{
	$value(^Data.int[])
}
^case[DEFAULT]{
	$value[$sData]
}
}

$new_value[$value]
^new_method[$value]


Последние 2 строки кода теряют значение в double. Добавлять при присвоении switch по типу выглядит не разумно.

Получается выхода два:
1. При работе с double в моем коде всегда делать $value[^sData.format[%f]] или с большим количеством знаков
Но при таком подходе при вызове без формата у меня всегда будет куча нулей.

2. Как и в 1 случае, но избавляться от лишних 0
$value(^sData.double[])
$value[^value.format[%f]]
$value[^value.match[\.?0+^$][]{}]


На мой взгляд было бы логично такое поведение:
$double(^sData.double[])

^method[$double]

@method[uData]


В метод придет double, а не stringт как сейчас.

Возможно ли это при учете передачи копии значения, а не ссылки. Или в чем я не прав со своей идеей?
#19Misha v.3
→ nkostya [#18] | 28.11.11 10:20 / 10:23
www.parser.ru → | ответить → | в избранное →
вообще-то изначально вы написали:

Итого мы получаем, что при преобразовании числа в double (см. 4 и 5) мы теряем правильное значение. Это ошибка или так задумывалось?


соотв. вам объяснили, почему при печати чисел происходит округление.

сейчас вы говорите про другой момент, который к сожалению присутствует.
увы, при передачи чисел в квадратных скобках происходит их "печать" с соотв. последствиями.
сделать иначе не получится, т.к. простой вывод в output -- это тоже печать, и тут число должно преобразовываться в строку.

думаю, вы можете "родить" свой класс Double, который решит всё проблемы. единственное -- красивого конструктора не получится.
#20nkostya
→ Misha v.3 [#19] | 28.11.11 12:55
www.parser.ru → | ответить → | в избранное →

Спасибо

Проблема понятна, как работать разобрался.

P.S. Я сначала так написал, т.к. не понял в какой момент теряется значение.
#21G_Z
→ nkostya [#18] | 28.11.11 13:00
www.parser.ru → | ответить → | в избранное →
Неясно как вы пишите некую схему хранения данных и тут же не знаете, что там double.

Храните, передавайте и присваиваете всегда в круглых скобках.
При преобразовании в число — задавайте формат.

Да, это необходимость озаботиться этими случаями, но не невозможно.
#22nkostya
→ G_Z [#21] | 28.11.11 13:19
www.parser.ru → | ответить → | в избранное →
Тип я знаю всегда, но я стараюсь при получении данных из "вне" (форма, БД) преобразовать его к типу Парсера. И т.к. при возврат значения происходит в методе объекта, который знает тип, а сохранение в массив происходит в классе, которые не знает типа, то и возникла вышеописанная проблема.
#23G_Z
→ nkostya [#22] | 28.11.11 13:38
www.parser.ru → | ответить → | в избранное →

Я всё же не понимаю

Вот код:
@main[]
$model[^DBModel::init[
	$.price[5000000.99]
	$.amount[15.887]
]]

$model.price.value<br/>
$model.amount.value

<hr/>

$model.price.value[1233333333.998]
$model.amount.value[12.001]
$model.price.value<br/>
$model.amount.value


@CLASS
DBDecimal

@init[value]
$self._value(^value.double(0))

@GET_value[]
$result[^self._value.format[%.3f]]

@SET_value[value]
$self._value(^value.double[])


@CLASS
DBModel

@init[data]
$self.price[^DBDecimal::init[$data.price]]
$self.amount[^DBDecimal::init[$data.amount]]


Никто кроме самого объекта поля о типе не задумывается.
Как здесь проявить вашу проблему?
#24nkostya
→ G_Z [#23] | 28.11.11 14:46
www.parser.ru → | ответить → | в избранное →

У меня DBField не хранит значение

Модель умеет только преобразовывать из одного типа в другой, сравнивать и т.д. Значение хранится в хеше.
Страницы форума: ← Назад | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 600 | Дальше →