16.10.2004, 09:23 | #41 |
Участник
|
Re: Нашедший ошибку
Цитата:
Изначально опубликовано REb
А я как раз человек, который эту ошибку обнаружил! ) ....И вот в этом отчете на реальных данных при расчете получалось два числа 9999.999999999999, которые при отображении показывались, действительно как 10000, но при сложении давали тоже 10000 ;((( Удалось обойти благодоря округлению сумм после умножения на коэфициент. Теперь аккуратнее отношусь к подобным вещам. Потому что по рекомендациям разработчиков Аксапты ПЕРЕД записью числа в базу данных необходимо выполнять метод currency::amountMST() или currency::Amount(). Эти методы выполняют округление согласно правилам округления в таблице валют. Вы просто не следовали рекомендациям. Вопрос здесь скорее в том, что подобные рекомендации должны быть доступны ВСЕМ разработчикам. Такие рекомендации должны бросаться в глаза в первую очередь... |
|
16.10.2004, 09:24 | #42 |
Участник
|
Цитата:
Изначально опубликовано savel
А дело даже не в хвостике. Точка может стоять в любом месте, и даже её может совсем не быть! Всё единно результат не правильный! Как только необходимо выполнять вычисления в 16ой цифрой - возникает ошибка. |
|
16.10.2004, 14:24 | #43 |
Участник
|
Цитата:
-------------------------------------------------------------------------------- Изначально опубликовано savel А дело даже не в хвостике. Точка может стоять в любом месте, и даже её может совсем не быть! Всё единно результат не правильный! -------------------------------------------------------------------------------- Muzzy, в том-то и проблема, что десятичная точка может стоять в ЛЮБОМ (!) месте и округлением это, к сожалению, не вылечишь. Кроме того, даже если бы это помогало - необходимо было бы при каждой арифметической операции делать округление а не только перед записью в базу. |
|
16.10.2004, 14:47 | #44 |
Участник
|
Цитата:
Изначально опубликовано Logger
Цитата: -------------------------------------------------------------------------------- Изначально опубликовано savel А дело даже не в хвостике. Точка может стоять в любом месте, и даже её может совсем не быть! Всё единно результат не правильный! -------------------------------------------------------------------------------- Muzzy, в том-то и проблема, что десятичная точка может стоять в ЛЮБОМ (!) месте и округлением это, к сожалению, не вылечишь. Кроме того, даже если бы это помогало - необходимо было бы при каждой арифметической операции делать округление а не только перед записью в базу. Без округления - это очень большие числа. Поэтому это маловероятно. Насчет округления в каждой арифметической операции. Если быть точным, то не в каждой, а при делении. Согласен, проблема серьезная. Паниковать не стоит, поскольку в стандартной Аксапте округления расставлены достаточно часто. Серьезные проблемы более вероятны в самописных модулях и в модификациях. Согласен, что это ошибка и ее надо исправлять. Но сейчас людям надо быстро найти обходной путь Еще раз: перед записью в базу обязательно надо вызывать currency::amount или currency::amountMST. Это рекомендация, близкая к стандарту. |
|
16.10.2004, 15:19 | #45 |
NavAx
|
а вот и первый ответ из МБС
"...Спасибо за детальный пример. Проблема уже зарегистрирована ранее в Product Studio для исправления командой SE, #2963. Принята к испавлению как критическая 29.09.2004. Ожидается исправленной в SP4, либо в kernel HF для него. Возможный обходной путь "The internal precision on reals in Aptata is 16 digits. The job below can be used to study what happens when we use all the digits and try to use one more. If you in the function myRound replaces 0.49 with 0.5 it will actually add one (the other option is to add 0). And that something like what the kernel does in the round function when if . If you add 0.49 it works on your 14 digits number. You COULD call myRound() instead of round() for numbers bigger than 10000000000000. (13 zeros, 14 digits) If you call it for smaller numbers we probably should not use the constant 0.49, but 0.49999…, so just call round() instead. static void JobTestRound(Args _args) { real myReal = 12345678901234.00; // 14 digits real r; real myRound(real r1, real r2) { real r3 = r1/r2; real r4; print "r3:", r3; r4 = trunc(r3+0.49); print "r4:", r4; return r4 * r2; } r = round(myReal, 0.01); print "round: ", r; r = myRound(myReal, 0.01); print "myRound:", r; pause; } Данный запрос будет обновлен по мере изменения статуса запроса от группы SE (группы разработки). Попробую добиться выпуска HF для SP3 для ядра ранее выхода SP4, но обещать не могу" Т.е. проблемка известна, признана критической чуть более двух недель назад. P.S. Вот такая мысль в голову пришла. А почему клиенты напрямую не допускаются к этой информации? Ну хотя бы в режиме чтения? Ведь пока мы сами такое не словим, мы и знать не будем что бывают ситуации когда 2+2=5. Впрочем равно как и по другим багам... Да хотябы по багам со статусом критичных, блин. Не понимаю я этого режима ЧРЕЗВЫЧАЙНОЙ секретности
__________________
И все они создания природы... |
|
16.10.2004, 15:37 | #46 |
Участник
|
Re: Re: Нашедший ошибку
Цитата:
Изначально опубликовано mazzy
А знаете почему у других подобных ошибок не возникало? Потому что по рекомендациям разработчиков Аксапты ПЕРЕД записью числа в базу данных необходимо выполнять метод currency::amountMST() или currency::Amount(). Эти методы выполняют округление согласно правилам округления в таблице валют. Вы просто не следовали рекомендациям. |
|
16.10.2004, 15:55 | #47 |
Участник
|
ну вы как маленькие.
перед любым использованием, перед возвратом из метода вызовите, до того, как показать пользователю вызовите метод округления. кстати, показывать display метод, который возвращает чистый real - моветон втройне. display метод должен возвращать тип из EDT. А там округление выполняется ядром. Хотя и здесь лучше вызвать currency::amount или currency::amountMST. Поскольку этим методы выполняют округление так, как настроено в справочнике валют. |
|
17.10.2004, 09:47 | #48 |
Участник
|
Да нет, же, mazzy, речь то о другом.
Ну и пусть вы храните числа в базе в округленном до n знаков после запятой виде. Это уменьшит число проблем связанных с данным глюком, но ни в коей мере не избавит от них. Посмотрите на следующий код - числа a и b совершенно целые, НЕ ДРОБНЫЕ И НЕ БОЛЬШИЕ, но ошибка (именно ошибка, а не тривиальная неточность округления в вещественной арифметике) происходит не при сохранении или извлечении из/в базу, а по ходу промежуточных вычислений над совершенно безобидными числами!!! PHP код:
(Изначально так и было написано что числа 9999.9999.... получены в результате вычислений, но не извлечены из базы) Операция деления становится совершенно небезопасной, т.к. может сгенерировать нам периодическую дробь из совершенно нормальных, округленных чисел, которая в свою очередь становится небезопасной при суммировании с другими периодическими дробями! Это же просто капец какой то. |
|
17.10.2004, 09:51 | #49 |
Участник
|
Re: Re: Нашедший ошибку
Цитата:
Изначально опубликовано mazzy
Потому что по рекомендациям разработчиков Аксапты ПЕРЕД записью числа в базу данных необходимо выполнять метод currency::amountMST() или currency::Amount(). Эти методы выполняют округление согласно правилам округления в таблице валют. |
|
17.10.2004, 10:30 | #50 |
Участник
|
Цитата:
Изначально опубликовано mazzy
ну вы как маленькие. перед любым использованием, перед возвратом из метода вызовите, до того, как показать пользователю вызовите метод округления. Будут новые глюки. |
|
17.10.2004, 21:51 | #51 |
Участник
|
Цитата:
Изначально опубликовано Alks
Да нет, же, mazzy, речь то о другом. Ну и пусть вы храните числа в базе в округленном до n знаков после запятой виде. Это уменьшит число проблем связанных с данным глюком, но ни в коей мере не избавит от них. Посмотрите на следующий код - числа a и b совершенно целые, НЕ ДРОБНЫЕ И НЕ БОЛЬШИЕ, но ошибка (именно ошибка, а не тривиальная неточность округления в вещественной арифметике) происходит не при сохранении или извлечении из/в базу, а по ходу промежуточных вычислений над совершенно безобидными числами!!! Баг. Я хотел бы обратить внимание тех, кто хочет найти решение до выходы СП на сообщение Максима Горбунова Цитата:
Изначально опубликовано Maxim Gorbunov
Опытным путем установлено, что если сумма цифр в последней позиции больше или равна 15, появляется ошибка. Для остальных значений работает верно. 1. кричать майкрософт масдай. А заодно и Навижин с Дамгаардом. 2. минимизировать вероятность проявления бага. Я бы хотел понять, что можно сделать для минимизации. |
|
29.10.2004, 14:03 | #52 |
Программер
|
Цитата:
Изначально опубликовано Alks
Да нет, же, mazzy, речь то о другом. Ну и пусть вы храните числа в базе в округленном до n знаков после запятой виде. Это уменьшит число проблем связанных с данным глюком, но ни в коей мере не избавит от них. Посмотрите на следующий код - числа a и b совершенно целые, НЕ ДРОБНЫЕ И НЕ БОЛЬШИЕ, но ошибка (именно ошибка, а не тривиальная неточность округления в вещественной арифметике) происходит не при сохранении или извлечении из/в базу, а по ходу промежуточных вычислений над совершенно безобидными числами!!! PHP код:
(Изначально так и было написано что числа 9999.9999.... получены в результате вычислений, но не извлечены из базы) Операция деления становится совершенно небезопасной, т.к. может сгенерировать нам периодическую дробь из совершенно нормальных, округленных чисел, которая в свою очередь становится небезопасной при суммировании с другими периодическими дробями! Это же просто капец какой то. |
|
02.11.2004, 11:56 | #53 |
MCTS
|
Не то чтоб ошибка...
Вот ещё. Не то, чтоб ошибка, но выглядит забавно:
PHP код:
__________________
Удачи. |
|
02.11.2004, 12:33 | #54 |
Участник
|
все правильно: 0x7fffffff*2 == 0x7fffffff<<1 == 0xfffffffe == -2
|
|
02.11.2004, 12:48 | #55 |
MCTS
|
Цитата:
все правильно
А так будет ещё забавней: PHP код:
__________________
Удачи. |
|
02.11.2004, 13:30 | #56 |
Участник
|
i*3 == i*2+i == -2 + i
|
|
05.11.2004, 07:27 | #57 |
NavAx
|
Цитата:
Изначально опубликовано vasiliy
А вы не используйте промежуточных переменных и все норм будет
__________________
И все они создания природы... |
|
Теги |
баг, математика, округление |
|
Похожие темы | ||||
Тема | Ответов | |||
Абстрактный классификатор | 52 | |||
Здравствуйте дети! :) - еще одна ошибка | 11 | |||
Просмотр SQL запросов к БД с помощью файла Log | 3 | |||
Виртуальные поля | 6 |
|