Автор | Сообщение |
|
| |
Пост N: 161
Зарегистрирован: 06.06.06
|
|
Отправлено: 22.03.20 11:45. Заголовок: Неправильная работа функции Int()
Всем привет! Все больше и больше тестирую свое ПО на Харборе. Работаю с большими числами и вот что выяснилось. Функция Int() работает с ошибками: Int(10^15) = 1000000000000000 Int(10^16) = 10000000000000002 :( Int(10^17) = 100000000000000016 :( Int(10^18) = 1000000000000000256 :( Int(10^19) = 10000000000000000000 Int(10^20) = 100000000000000000000 Кстати, на Клиппере все OK. Харбор 3.2 февральский. Это можно как-то исправить?
|
|
|
Ответов - 14
[только новые]
|
|
|
| |
Пост N: 162
Зарегистрирован: 06.06.06
|
|
Отправлено: 22.03.20 11:56. Заголовок: Может быть, проблема..
Может быть, проблема в функции Round(): Round(10^15,0) = 1000000000000000 Round(10^16,0) = 10000000000000002 :( Round(10^17,0) = 100000000000000016 :( Round(10^18,0) = 1000000000000000256 :( Round(10^19,0) = 10000000000000000000 Round(10^20,0) = 100000000000000000000
|
|
|
|
| |
Пост N: 7177
Зарегистрирован: 17.05.05
|
|
Отправлено: 22.03.20 12:46. Заголовок: http://clipper.borda..
|
|
|
|
| |
Пост N: 163
Зарегистрирован: 06.06.06
|
|
Отправлено: 22.03.20 17:43. Заголовок: Dima, спасибо, но я ..
Dima, спасибо, но я не могу понять, почему результат разный n := 10000000000000000 // 17 цифр Int(n) = Round(n,0) = 10000000000000000 // OK n := 10^16 // те же 17 цифр Int(n) = Round(n,0) = 10000000000000002 // :(
|
|
|
|
| |
Пост N: 164
Зарегистрирован: 06.06.06
|
|
Отправлено: 22.03.20 17:54. Заголовок: Если поставить десят..
Если поставить десятичную точку, то вылезает та же двойка n := 10000000000000000.0 // 17 цифр Int(n) = Round(n,0) = 10000000000000002 // :(( n := 10^16 // те же 17 цифр Int(n) = Round(n,0) = 10000000000000002 // :((
|
|
|
|
| |
Пост N: 165
Зарегистрирован: 06.06.06
|
|
Отправлено: 22.03.20 17:58. Заголовок: n := 10^16 // те же ..
n := 10^16 // те же 17 цифр Int(n) = Round(n,0) = 10000000000000002 // А вот так работает: n := Val(Str(10^16,20,0)) // те же 17 цифр Int(n) = Round(n,0) = 10000000000000000 //
|
|
|
|
| Администратор
|
Пост N: 3926
Зарегистрирован: 23.05.05
|
|
Отправлено: 22.03.20 21:58. Заголовок: ort пишет: Dima, сп..
ort пишет: цитата: | Dima, спасибо, но я не могу понять, почему результат разный n := 10000000000000000 // 17 цифр Int(n) = Round(n,0) = 10000000000000000 // OK n := 10^16 // те же 17 цифр Int(n) = Round(n,0) = 10000000000000002 // :( |
| В первом случае внутреннее представление n - это 64-битное целое, без потери точности. Во втором случае n представлено как double с потерей точности, так как значности 52-х битной мантиссы уже не хватает. Результат 2^n тоже будет double с потерей точности Странно не то, что харбор дает потерю точности, как раз так и должно быть. Странно то, что 16-битный клиппер работает без потери точности. В харборе функция int реализована через сишную функцию modf, завтра попробую глянуть, как это сделано в клиппере.
|
|
|
|
| |
Пост N: 166
Зарегистрирован: 06.06.06
|
|
Отправлено: 23.03.20 00:57. Заголовок: Pasha пишет: В перв..
Pasha пишет: цитата: | В первом случае внутреннее представление n - это 64-битное целое, без потери точности. Во втором случае n представлено как double с потерей точности, так как значности 52-х битной мантиссы уже не хватает. Результат 2^n тоже будет double с потерей точности |
| До меня тоже уже дошло! Паша, а почему во втором случае результат правильный? Round(10^18,0) = 1000000000000000256 :( Round(10^19,0) = 10000000000000000000
|
|
|
|
| Администратор
|
Пост N: 3927
Зарегистрирован: 23.05.05
|
|
Отправлено: 23.03.20 19:21. Заголовок: ort пишет: Функция ..
ort пишет: цитата: | Функция Int() работает с ошибками: Int(10^15) = 1000000000000000 Int(10^16) = 10000000000000002 :( Int(10^17) = 100000000000000016 :( Int(10^18) = 1000000000000000256 :( Int(10^19) = 10000000000000000000 Int(10^20) = 100000000000000000000 Кстати, на Клиппере все OK. |
| Ну хоть на этот вопрос ответ нашелся. В функции int (и round) харбора зачем-то используется такой трюк: #if defined( HB_DBLFL_PREC_FACTOR ) && ! defined( HB_CLP_STRICT ) /* Similar hack as in round to make this functions compatible */ dNum *= HB_DBLFL_PREC_FACTOR; #endif HB_DBLFL_PREC_FACTOR это #define HB_DBLFL_PREC_FACTOR 1.0000000000000002; кто это сделал, когда и для какой совместимости - непонятно. Но как раз для 10**16 и выше это и дает погрешность. Если убрать умножение на 1.0000000000000002, то результат становится правильным, как и в клиппере. Может быть это умножение для чего-то и нужно, но не для нашего случая
|
|
|
|
| |
Пост N: 168
Зарегистрирован: 06.06.06
|
|
Отправлено: 23.03.20 22:19. Заголовок: Паша, погрешность то..
Паша, погрешность только для 10^16, 10^17, 10^18, а для 10^19 и больше ее нет.
|
|
|
|
| |
Пост N: 169
Зарегистрирован: 06.06.06
|
|
Отправлено: 23.03.20 22:26. Заголовок: Паша, вот что я наше..
Паша, вот что я нашел в файле C:\hb32\include\hbdefs.h: /* This value is used to hack the double FL value in round/int operation - similar thing is done by CL5.3 - I do not know only the exact factor value but it should be close to this one. When HB_CLP_STRICT is set this macro is not used. */ #define HB_DBLFL_PREC_FACTOR 1.0000000000000002; Приблизительный перевод: Это значение используется для взлома значения FL double в операции round/int аналогично CL5.3 - не знаю только точное значение множителя, но оно должно быть близко к этому. Когда HB_CLP_STRICT определено, этот макрос не используется.
|
|
|
|
| Администратор
|
Пост N: 3928
Зарегистрирован: 23.05.05
|
|
Отправлено: 23.03.20 22:57. Заголовок: Да, до 2004 года реа..
Да, до 2004 года реализация int была через вызовы floor/ceil. Затем было несколько переделок, в результате все пришло к такому виду. В комментариях еще написано, что точность гарантируется вплоть до 15-ти знаков, а больше в бизнес-процессах и не надо. Якобы в клиппере 5.3 так делается. Я запускал тесты на клиппере 5.2, там вроде такого нет. На 5.3 не собирал. Сейчас на 64-битных системах собирать клиппер-программы то еще удовольствие. Можно сделать свой аналог INT, без такой корректировки, чтобы не пересобирать харбор с макросом HB_CLP_STRICT: #pragma BEGINDUMP #include "hbapi.h" #include "hbapiitm.h" #include "hbapierr.h" #include "hbmath.h" HB_FUNC( MY_INT ) { PHB_ITEM pNumber = hb_param( 1, HB_IT_NUMERIC ); if( pNumber ) { if( HB_IS_NUMINT( pNumber ) ) hb_itemReturn( pNumber ); else { int iWidth; double dInt; ( void ) modf( hb_itemGetND( pNumber ), &dInt ); hb_itemGetNLen( pNumber, &iWidth, NULL ); hb_retnlen( dInt, iWidth, 0 ); } } else hb_errRT_BASE_SubstR( EG_ARG, 1090, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); } #pragma ENDDUMP
|
|
|
|
|
| постоянный участник
|
Пост N: 3101
Зарегистрирован: 17.02.12
|
|
Отправлено: 24.03.20 00:18. Заголовок: Pasha пишет Сейчас ..
Pasha пишет цитата: | Сейчас на 64-битных системах собирать клиппер-программы то еще удовольствие. |
| С DosBox на 64 битных системах отлично clipper от Summer 87 и далее работает и собирается. Можно запустить VC (Волков командер, дос редактор, драйвер клавиатуры как в дос и т.д.) и работать как в дос под ним. Есть ветви от DosBox. Товарищ по работе использует DosBox plus (не уточнял точное название). Он добавил фонты латышские, там работают Windows Run с ожиданием и без и есть какие то свои примочки и все ok. Знаю только с его слов пока, т.к. свои проги (на bat файлах) clipper+hb+vo+wvt пошли с DosBox из темы http://clipper.borda.ru/?1-0-0-00000601-000-0-0-1578415122 под управлением менеджера на hmg ext.
|
|
|
|
| |
Пост N: 170
Зарегистрирован: 06.06.06
|
|
Отправлено: 24.03.20 00:41. Заголовок: Pasha пишет: Можно ..
Pasha пишет: цитата: | Можно сделать свой аналог INT, без такой корректировки, чтобы не пересобирать харбор с макросом HB_CLP_STRICT: |
| Спасибо, Паша, так и сделаю!
|
|
|
|
| Администратор
|
Пост N: 3929
Зарегистрирован: 23.05.05
|
|
Отправлено: 24.03.20 07:26. Заголовок: SergKis пишет: С Do..
SergKis пишет: цитата: | С DosBox на 64 битных системах отлично clipper от Summer 87 и далее работает и собирается. Можно запустить VC (Волков командер, дос редактор, драйвер клавиатуры как в дос и т.д.) и работать как в дос под ним. |
| Именно этими продуктами я и пользуюсь
|
|
|
|