|
![]() |
#1 |
Участник
|
Цитата:
при стандартных региональных настройках в панели управления, преобразование из числа в строку а затем из строки в число работает некорректно: X++: s = num2str(123456.78, 10, 2, -1, -1); // s ="123 456.78" (с пробелом, код которого = 32) num = str2num(s); // num = 123, в то время как ожидалось 123456.78 !!! |
|
![]() |
#2 |
Участник
|
strrem vs strkeep
Цитата:
Сообщение от valentino
X++: s = strrem(s, thousandsSeparator); // ничего не происходит Цитата:
Сообщение от valentino
![]() X++: s = num2str(123456.78, 10, 2, -1, -1); // s ="123 456.78" (с пробелом, код которого = 32) num = str2num(s); // num = 123, в то время как ожидалось 123456.78 !!! X++: static void jobRemoveThousandsSeparator(Args _args) { #define.Numerics( ',.+-0123456789e' ) str s = num2str( 123456.78, 10, 2, -1, -1 ) ; real num = str2num( strkeep( s, #Numerics ) ) ; ; info( strfmt( "%1", num ) ) ; }
__________________
Dynamics AX 4.0 SP2 Последний раз редактировалось in.dc; 29.04.2009 в 12:34. Причина: вариант с strkeep чуть раньше упомянул Hyper |
|
|
За это сообщение автора поблагодарили: valentino (1). |
![]() |
#3 |
Участник
|
Цитата:
Сообщение от valentino
![]() Может я недостаточно четко сформулировал вначале, суть сводится к следующему:
при стандартных региональных настройках в панели управления, преобразование из числа в строку а затем из строки в число работает некорректно: X++: s = num2str(123456.78, 10, 2, -1, -1); // s ="123 456.78" (с пробелом, код которого = 32) num = str2num(s); // num = 123, в то время как ожидалось 123456.78 !!! Вы описали бессмысленную, с моей точки зрения, задачу. Преобразовать число в строку, а затем из полученной строки снова сделать число. Зачем? Почему нельзя было взять исходной число без этих преобразований? Есть правила перевода числа в строку. Есть правила перевода строки в число. Эти правила вовсе не обязаны быть взаимно-однозначны. Могут, но не обязательно. Попробуйте сформулировать, хотя бы для самого себя, какова конечная цель? Вы хотите, чтобы алгоритмы преобразования число-строка и строка-число были взаимно-однозначны? По каким правилам? Почему правила должны быть именно такими? Или вам надо преобразовать вполне конкретную символьную строку (сформированную по определенным правилам) в число? Если стоит всего-лишь вторая задача, то посмотрите мой пример преобразования символьной строки в число. Алгоритм достаточно сложен. А ведь я это писал под вполне конкретную задачу. Хотя и постарался сделать код, по-возможности, достаточно универсальным. Код: // Конвертация символьной строки в число // Данный метод не анализирует возможность того, что один из разделителей может являться частью другого // Например, разделитель целой и дробной части - это две точки подряд, а разделитель троек цифр - одна точка // Последствия использования подобных разделителей в данном методе могут быть парадоксальными (не ожидАемыми) // Примеры вызова /* print global::rtg_str2num("123.45"); // 123.45 print global::rtg_str2num("1 234 567.89"); // 1234567.89 print global::rtg_str2num("1 234 567.89e-2"); // 12345.6789 print global::rtg_str2num("1 234 567,89",","); // 1234567.89 print global::rtg_str2num("123,5","","",","); // 123e5 = 12 300 000 print global::rtg_str2num("123.4,1","","",","); // 123.4e1 = 1234 print global::rtg_str2num("123e4.1","e","","."); // 123.4e1 = 1234 print global::rtg_str2num("123e4","e","","."); // 123.4 pause; return; */ #define.point(".") #define.separator(" ") #define.base("e") public static real rtg_str2num( str _string, // собственно строка, которую надо перевести "123 456.78" str _point = #point, // разделитель целой и дробной части str _separator = #separator, // разделитель троек цифр str _base = #base // Основание. Разделитель мантиссы и порядка числа, если оно представлено в форме "123e-2" ) { ; // Как правило, параметр не указывают, если хотят указать значение параметра, следующего за ним, // а значение пропущенного параметра предполагается считать значением по умолчанию if (! _point) { _point = #point; } if (! _separator) { _separator = #separator; } if (! _base) { _base = #base; } // Ситуация, когда разные разделители имеют одно и то же значение рассматривается как ошибка, // поскольку становится невозможно выделить нужные части строки if (_point == _separator) { throw error(strFmt("Разделитель целой и дробной части \"%1\" не может быть равен разделителю троек цифр \"%2\"",_point, _separator)); } if (_point == _base) { throw error(strFmt("Разделитель целой и дробной части \"%1\" не может быть равен разделителю мантиссы и порядка числа \"%2\"",_point, _base)); } if (_separator == _base) { throw error(strFmt("Разделитель троек цифр \"%1\" не может быть равен разделителю мантиссы и порядка числа \"%2\"",_separator, _base)); } // Удаляю ведущие и концевые пробелы // Вообще все пробелы удалять нельзя, поскольку какой-либо символ разделитель может содержать или быть пробелом // Хотя, в принципе, эту операция можно вообще не делать, поскольку функции str2num() эти пробелы не мешают _string = global::strLRTrim(_string); // Удаляю символы разделители троек цифр if (_separator) { if (strLen(_separator) == 1) { _string = strRem(_string, _separator); } else { // Здесь strRem() использовать нельзя, поскольку необходимо удалить именно // определенную последовательность символов, а не отдельные символы _string = global::strReplace(_string, _separator, ""); } } // Если необходимо сделать две последовательные замены одного набора символов на другой, // то необходимо убедтиться в том, что вторая замена не "затрет" результат первой // т.е. в результате первой замены не должны появиться символы, которые заменит вторая замена switch (true) { case ((_base != #base) && (_point != #point) && (_point == #base) && (_base == #point)) : // Здесь нужна промежуточная замена на символы, которые не равны ни _point, ни _base // Подойдет _separator, поскольку это значение уже было проверено на данное равенство // и последовательность символов _separator была удалена из строки _string = global::strReplace(_string, _base, _separator); _string = global::strReplace(_string, _point, #point); _string = global::strReplace(_string, _separator, #base); break; case ((_base != #base) && (_point != #point) && (_point == #base)) : _string = global::strReplace(_string, _point, #point); _string = global::strReplace(_string, _base, #base); break; case ((_base != #base) && (_point != #point) && (_base == #point)) : _string = global::strReplace(_string, _base, #base); _string = global::strReplace(_string, _point, #point); break; default : if (_point != #point) { _string = global::strReplace(_string, _point, #point); } if (_base != #base) { _string = global::strReplace(_string, _base, #base); } break; } return str2num(_string); } |
|
![]() |
#4 |
Moderator
|
Попробую еще раз.
МОЕ ПОНИМАНИЕ ПРОБЛЕМЫ: Цитата:
Цитата:
X++: static void Job173(Args _args) { real a = 123456.78; str strNumberAfterStrFmt = strFmt('%1', a); real b; boolean c; ; b = str2Num( strFmt ( '%1e-2', strKeep( strNumberAfterStrFmt, '-0123456789'))); c = a == b; box::info(strFmt('%1\n\n%2\n\n%3', strFmt('Исходное число: %1', a), strFmt('Восстановленное число из строки: %1', b), strFmt('Исходное число равно числу из строки?: %1', c))); } В процессе эксперимента обратил внимание на то, что региональные настройки Аксапта считывает при старте приложения и далее в текущей сессии их не меняет (!) даже при изменении региональных настроек в панели управления. Такое поведение Аксапты отличается, например, от поведения Excel, где при смене локали c Russian на English (United States) наглядно видно, как в ячейке тут же меняются разделители тысяч с пробелов на запятые. Последний раз редактировалось Gustav; 30.04.2009 в 09:42. |
|
|
За это сообщение автора поблагодарили: aidsua (1). |
Теги |
разделитель тысячных, axapta |
|
![]() |
||||
Тема | Ответов | |||
Разделитель страницы в MS WORD | 3 | |||
Разделитель десятичных знаков в отчетах | 0 |
Опции темы | Поиск в этой теме |
Опции просмотра | |
|