On-line: гостей 0. Всего: 0 [подробнее..]
АвторСообщение





Пост 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 февральский.
Это можно как-то исправить?

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 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

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 7177
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 22.03.20 12:46. Заголовок: http://clipper.borda..

Спасибо: 1 
ПрофильЦитата Ответить





Пост 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 // :(

Спасибо: 0 
ПрофильЦитата Ответить





Пост 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 // :((

Спасибо: 0 
ПрофильЦитата Ответить





Пост 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 //

Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост 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, завтра попробую глянуть, как это сделано в клиппере.

Спасибо: 1 
ПрофильЦитата Ответить





Пост 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

Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост 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, то результат становится правильным, как и в клиппере.
Может быть это умножение для чего-то и нужно, но не для нашего случая

Спасибо: 1 
ПрофильЦитата Ответить





Пост N: 168
Зарегистрирован: 06.06.06
ссылка на сообщение  Отправлено: 23.03.20 22:19. Заголовок: Паша, погрешность то..


Паша, погрешность только для 10^16, 10^17, 10^18, а для 10^19 и больше ее нет.

Спасибо: 0 
ПрофильЦитата Ответить





Пост 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 определено, этот макрос не используется.


Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост 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


Спасибо: 1 
ПрофильЦитата Ответить
постоянный участник




Пост 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.

Спасибо: 1 
ПрофильЦитата Ответить





Пост N: 170
Зарегистрирован: 06.06.06
ссылка на сообщение  Отправлено: 24.03.20 00:41. Заголовок: Pasha пишет: Можно ..


Pasha пишет:

 цитата:
Можно сделать свой аналог INT, без такой корректировки, чтобы не пересобирать харбор с макросом HB_CLP_STRICT:


Спасибо, Паша, так и сделаю!

Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 3929
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 24.03.20 07:26. Заголовок: SergKis пишет: С Do..


SergKis пишет:

 цитата:
С DosBox на 64 битных системах отлично clipper от Summer 87 и далее работает и собирается.
Можно запустить VC (Волков командер, дос редактор, драйвер клавиатуры как в дос и т.д.) и работать как в дос под ним.



Именно этими продуктами я и пользуюсь

Спасибо: 0 
ПрофильЦитата Ответить
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 18
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет