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





Пост N: 311
Зарегистрирован: 12.11.06
ссылка на сообщение  Отправлено: 10.12.15 17:57. Заголовок: xHarbour и возможно Harbour неправильно складывает! Как победить?


В задачах по ЕГАИС нужно переводить 36 ричное число в десятиричное и отображать в виде строки дополненное нулями. Есть конкретные значения

22N00001CJFID3CDJKV3SXP412170130000055IEUMY72S745DV7196PEFENFADYFS4F - код акцизной марки
1CJFID3CDJKV - преобразуем данный блок
0177469000003644511 - ПРАВИЛЬНОЕ число по "1С" или Web трансляторам
0177469000003644661 - считает xHarbour по "ручным" алгоритмам или через встроенные функции
0177469000003644662 - считает xHarbour, если nSum задать, как комментарии

Код моих "мучений":
 
nLen := Len( cA )
cB := cA

nSum := 0 // 0.0000
FOR nX := 1 TO nLen
nM := 1
FOR nY := 1 TO nLen - nX DO nM := nM*36

nSum := nSum + nM * ( At( Subs(cA,nX,1), "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ) - 1 )
NEXT nX

cA := Ntoc( nSum, 10, 19, "0" )
WAIT cA+" "+Ntoc( Cton(cB,36), 10, 19, "0" )



Подскажите пожалуйста, хоть вставкой на С - уже мозги кипят

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 15 [только новые]


администратор




Пост N: 710
Зарегистрирован: 20.02.11
ссылка на сообщение  Отправлено: 10.12.15 18:23. Заголовок: AndreyZh пишет: 1CJ..


AndreyZh пишет:

 цитата:
1CJFID3CDJKV - преобразуем данный блок
0177469000003644511 - ПРАВИЛЬНОЕ число по "1С" или Web трансляторам



CTON( '1CJFID3CDJKV', 36 ) = 177469000003644511


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




Пост N: 5398
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 10.12.15 18:27. Заголовок: Haz пишет: CTON( &#..


Haz пишет:

 цитата:
CTON( '1CJFID3CDJKV', 36 ) = 177469000003644511


Результат в PADL и добиваем нулями.

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




Пост N: 711
Зарегистрирован: 20.02.11
ссылка на сообщение  Отправлено: 10.12.15 18:30. Заголовок: Dima пишет: Результ..


Dima пишет:

 цитата:
Результат в PADL и добиваем нулями.



PADL(CTON( '1CJFID3CDJKV', 36 ), 19, '0')

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





Пост N: 312
Зарегистрирован: 12.11.06
ссылка на сообщение  Отправлено: 10.12.15 18:40. Заголовок: Делаю "то же"..


Делаю "то же" самое: Ntoc( Cton(cB,36), 10, 19, "0" ) ... что глючит Ntoc или комп - сейчас проверю ваши рекомендации

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




Пост N: 5399
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 10.12.15 18:42. Заголовок: AndreyZh пишет: Дел..


AndreyZh пишет:

 цитата:
Делаю "то же" самое: Ntoc( Cton(cB,36), 10, 19, "0" )


нет не тоже
Haz пишет:

 цитата:
PADL(CTON( '1CJFID3CDJKV', 36 ), 19, '0')



Вот так можно (не проверял)
PADL(Ntoc( Cton(cB,36) ), 19, "0" )

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




Пост N: 5400
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 10.12.15 18:59. Заголовок: AndreyZh пишет: Nto..


AndreyZh пишет:

 цитата:
Ntoc( Cton(cB,36), 10, 19, "0" )


Проверил именно такой код
результат 0177469000003644511

ЗЫ
Harbour

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





Пост N: 313
Зарегистрирован: 12.11.06
ссылка на сообщение  Отправлено: 10.12.15 19:00. Заголовок: Всем огромное СПАСИБ..


Всем огромное СПАСИБО!!!

Успокоили, что xHarbour считает ПРАВИЛЬНО, как при использовании Cton, так и при алгоритме преобразования, но НЕПРАВИЛЬНО тогда работают функции:

ПРАВИЛЬНО Padl( nSum, 19, "0" ) или Padl( Cton(cB,36), 19, "0" )
НЕПРАВИЛЬНО Padl( Ntoc(nSum), 19, "0" ) или Padl( Alltrim(Str(nSum,19)), 19, "0" ) или Ntoc( nSum, 10, 19, "0" ) или Ntoc( Cton(cB,36), 10, 19, "0" )

то есть "глючат" Ntoc, Str?


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




Пост N: 3378
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 10.12.15 19:03. Заголовок: harbour поддерживает..


[x]harbour поддерживает тип LONGLONG (64 битные целые), точности которого достаточно для представления 12-значного целого с базой 36.
Если nSum задать как 0.0, будет использоваться тип double, точности которого уже недостаточно, вот и результат будет с погрешностью.
Код ваших мучений считает nSum правильно, поскольку задействуется только тип LONGLONG.
Дальнейшее использование cton/ntoc излишне.
Чтобы перевести nSum в строку, достаточно вызвать Str(nSum, 19), ну и заменить ведущие пробелы на нули.


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





Пост N: 314
Зарегистрирован: 12.11.06
ссылка на сообщение  Отправлено: 10.12.15 19:04. Заголовок: Dima пишет: Dima п..


Dima пишет:
[quote]` Dima пишет:

 цитата:
Проверил именно такой код
результат 0177469000003644511


Такой был изначально и не работал... да и сейчас перепроверял Windows 7/64

Как бы то ни было ВЫ МНЕ ВСЕ ОЧЕНЬ СИЛЬНО ПОМОГЛИ!!!

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





Пост N: 315
Зарегистрирован: 12.11.06
ссылка на сообщение  Отправлено: 10.12.15 19:18. Заголовок: А ВОТ И НИ ФИГА!!! ..


А ВОТ И НИ ФИГА!!!

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

Примеры правильных результатов:

1CJFID3CD
0177469000003644511

1CJFID3CE
0177469000003704221

54KNI68SC
0150367000002817036

Уже не получается...

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




Пост N: 5401
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 10.12.15 19:43. Заголовок: AndreyZh пишет: 1CJ..


AndreyZh пишет:

 цитата:
1CJFID3CD


Да тут и строка покороче будет чем в первом посте , возможно дело не в этом

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





Пост N: 316
Зарегистрирован: 12.11.06
ссылка на сообщение  Отправлено: 10.12.15 19:53. Заголовок: Сегодня уже не в себ..


Сегодня уже не в себе... Действительно не работает, но коды я беру с оборудования. Вероятно в сообщение неправильно скописпастил... С Вашего разрешения, завтра на свежую голову набросаю кучу примеров, где есть неверная перекодировака

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




Пост N: 3379
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 10.12.15 19:57. Заголовок: В xHarbour функции c..


В xHarbour функции cton/ntoc реализованы в коде prg
Например, там есть строка вроде

nInt := INT( nNum / nBase)

Рерультат nNum / nBase будет иметь тип double, а использование этого типа для таких больших чисел может приводить к погрешности.
В Harbour эти функции сделаны на С, там погрешности быть не может.


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




Пост N: 5402
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 10.12.15 22:19. Заголовок: AndreyZh В этой тем..


AndreyZh
В этой теме много пишут (я особо не вникал , так как не в теме)
http://olegon.ru/showthread.php?t=23079&page=26

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





Пост N: 317
Зарегистрирован: 12.11.06
ссылка на сообщение  Отправлено: 11.12.15 09:05. Заголовок: Dima пишет: В этой ..


Dima пишет:

 цитата:
В этой теме много пишут (я особо не вникал , так как не в теме) http://olegon.ru/showthread.php?t=23079&page=26


Это обсуждение моей "мегасистемы" под ЕГАИС, в которой и возникла данная "заморочка", но с Ваше Dima, Pasha проникся сутью проблемы и кажется с Вашей помощью её полностью победил. Для других читателей:

1. Считает (x)Harbour правильно, но не всегда с требуемой точностью. Например задавая nSum:=0.0 вынуждал его работать с малой точностью Double, что приводило к округлениям на больших числах, а надо было (=0), что уже приводило к работе с длинными целыми;
2. Также использовании Cton/Ntoc использовались операции, приводящие к округлениям. На небольших числах этого не замечалось, но в моей заморочке давало неверный результат.

Правильно работающий код сегодня проверенный на 10 акцизках и сличении с примерами транслятора: http://www.translatorscafe.com/cafe/units-converter/numbers/calculator/decimal-to-base-36/

 
cCod := Upper( Alltrim(cCod) )
IF Len(cCod) <> 68 THEN Errmess("Длина кода акцизной марки точно равняется 68 знакам! У Вас не так = "+Str(Len(cCod),2),cError); RETU

/* Номер не всегда начинается с 9 знака - более сложный алгоритм его выделения. Код АП правильно
определяется в случае вхождения 00000 иначе никак не смог получить правильный код - какая-то лажа или
с примерами марок (старые) или с алгоритмом
10.12.2015 Использую алгоритмы ручного преобразования из 36 ричного числа в 19 значное 10 ричное представление */
cTabWorker := cCod // Для передачи в отчет ШК акцизной марки

// Выбираем разное число преобразуемых кодов
IF Subs( cCod,4,5 ) == "00000"
cA := Subs( cCod,9,11 )
ELSE
cA := Subs( cCod,8,12 )
ENDI
nLen := Len( cA )
cB := cA

// Расчет в десятиричной систем (=0) делает переменную LongInteger, а если (=0.0) то Double, что уменьшает точность
nSum := 0
FOR nX := 1 TO nLen
nM := 1
FOR nY := 1 TO nLen - nX DO nM := nM*36

nSum := nSum + nM * ( At( Subs(cA,nX,1), "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ) - 1 )
NEXT nX

// Варианты использования Ntoc(nSum), Str(nSum,19) приводят к округлениям и потери точности
cA := Padl( nSum, 19, "0" ) // Просто выравнием число пополняя нулями

@ 0,0 SAY cA+" "+cTabWorker
Inkey( 0 )


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

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