Перейти к содержимому


Фотография

Как преобразовать длинный номер в текст без искажения ?


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 19

#1 OFFLINE   barbosa

barbosa

    Ефрейтор

  • Пользователи
  • 99 сообщений

Отправлено 19 March 2019 - 23:32

Всем привет, подскажите как длинный номер показать в hint без искажения ?
Например _id = 76561197980000000;
Пробовал str(id), format ["%1",_id], это не решает проблему.
Буду очень благодарен за помощь.
  • 0

#2 OFFLINE   vlad333000

vlad333000

    Полковник

  • Пользователи
  • 3224 сообщений
  • Откуда:Кострома

Отправлено 20 March 2019 - 02:35

barbosa, конечно это не решает проблему т. к. str работает на этапе исполнения, а не компиляции, на котором он преобразуется из исходного кода в переменную типа float (из-за чего числу и не хватает точности):
Через тип STRING:
private _id = "12345678901234567890";
hint format ["id = %1", _id];
Или препроцессорнуб директиву "str":
#define STR(A) #A
hint format ["id = %1", STR(12345678901234567890)];
Думаю объяснять то, что прямых арифметических операций над данным числом вы проводить не можете и нужно писать свои функции?
  • 0

#3 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 20 March 2019 - 17:57

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

Имя функции не помню, и поискать не получится, арма снесена месяца 3 как уже.


Сообщение отредактировал SteelRat: 20 March 2019 - 17:58

  • 0

#4 OFFLINE   ReXcOr

ReXcOr

    Ст.сержант

  • Пользователи
  • 264 сообщений
  • Откуда:Moscow

Отправлено 21 March 2019 - 14:37

result = [999999999] call BIS_fnc_numberText


  • 0

#5 OFFLINE   ReXcOr

ReXcOr

    Ст.сержант

  • Пользователи
  • 264 сообщений
  • Откуда:Moscow

Отправлено 21 March 2019 - 16:01

Вообще, судя по ID, вы используете именно UID, тогда я не пойму, зачем вы его пытаетесь из int переделать в string, когда с помощью команды getPlayerUID вы его получаете как раз таки в виде string?

Да и все хэндлеры на коннект/дисконнект, возвращают вам этот параметр в виде string

Нафига?))))

Или если вы генерируете свой ID, для того что-бы вносить его в БД, делайте его изначально как string

И вообще, функция от бисов, та что выше - Bis_fnc_numberText, конвертирует криво, если передавать в нее слишком длинное значение, так что не стоит выбирать такие пути, ведь с UID работать изи, когда он в string, это так задумано и нам не надо ничего изобретать

Ну или если у вас другие цели, вы нас посвятите, может чем поможем ещё


Сообщение отредактировал ReXcOr: 21 March 2019 - 16:08

  • 0

#6 OFFLINE   vlad333000

vlad333000

    Полковник

  • Пользователи
  • 3224 сообщений
  • Откуда:Кострома

Отправлено 21 March 2019 - 17:49

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

Если вы про это:

BIS_fnc_numberText

То она делает немного другое: преобразует число в строку без экспоненциальной записи (scientific notation), которая может появится при использовании обычной команды str, длинна ограничена точностью представления оригинального числа.
Другой функции работы с большими числами, я не нашел в стандартном наборе функций от BIS'ов.

И вообще, функция от бисов, та что выше - Bis_fnc_numberText, конвертирует криво, если передавать в нее слишком длинное значение

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

Сообщение отредактировал vlad333000: 21 March 2019 - 17:54

  • 0

#7 OFFLINE   ReXcOr

ReXcOr

    Ст.сержант

  • Пользователи
  • 264 сообщений
  • Откуда:Moscow

Отправлено 21 March 2019 - 20:25

 

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

Если вы про это:

BIS_fnc_numberText

То она делает немного другое: преобразует число в строку без экспоненциальной записи (scientific notation), которая может появится при использовании обычной команды str, длинна ограничена точностью представления оригинального числа.
Другой функции работы с большими числами, я не нашел в стандартном наборе функций от BIS'ов.

И вообще, функция от бисов, та что выше - Bis_fnc_numberText, конвертирует криво, если передавать в нее слишком длинное значение

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

 

Про тонкости с SQF, не знал, спасибо, буду иметь это ввиду


  • 0

#8 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 21 March 2019 - 20:38

64 бит система, Windows

Выводы делаем сами.

 

Прикрепленный файл  screenday_01.jpg   80.17К   0 Количество загрузок:


  • 0

#9 OFFLINE   ReXcOr

ReXcOr

    Ст.сержант

  • Пользователи
  • 264 сообщений
  • Откуда:Moscow

Отправлено 21 March 2019 - 21:00

64 бит система, Windows

Выводы делаем сами.

 

attachicon.gifscreenday_01.jpg

Хороший пример, собственно видно, что UID в int не вместится, так что - выбираем string ))

Я пока с трудом представляю ситуацию, когда и для чего вообще может понадобиться конвертнуть UID в int

Только для розыгрыша счастливого UID по БД??? Лол

И то рандомным селектом можно обойтись


Сообщение отредактировал ReXcOr: 22 March 2019 - 02:50

  • 0

#10 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 21 March 2019 - 21:04

UID по определению и рассматривается на уровне типизации как string, и UID совсем не обязан представлять из себя чисто набор чисел.

Это

afsgeARTnbsmndfj45Jdjkfglgl

тоже вполне себе какой ни будь ID.

 

Любой ID, по сути, это маркер, который может быть набором любых символов.

 

ЗЫ

На уровне С и С++ тип string представляет из себя массив хранящий типы char, то есть символы, то есть, букафки, циферки, и спец знаки.


Сообщение отредактировал SteelRat: 21 March 2019 - 21:18

  • 0

#11 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 21 March 2019 - 21:13

 

Я пока с трудом представляю ситуацию, когда и для чего вообще может понадобиться конвертнуть UID в int

По факту, в этом нет ни какого смысла.


  • 0

#12 OFFLINE   vlad333000

vlad333000

    Полковник

  • Пользователи
  • 3224 сообщений
  • Откуда:Кострома

Отправлено 21 March 2019 - 22:41

64 бит система, Windows
Выводы делаем сами.
attachicon.gifscreenday_01.jpg

Во-первых, в вашем примере тип double (double precision float point), когда арма использует float (single precision float point)
Во-вторых, минимальное и максимальное число для числа с плавающей точкой определяется как max/min мантиссы умноженное на основание с максимальной степенью, что даже для одинарной точности - число с 127 нулями, что больше, чем 64-разрядное целое.
Важно не макс/мин, а кол-во знаков которые могут быть точно представлены, что примерно: 7 (float) и 15 (double) десятичных разрядов, что меньше чем 9 у int32 и 20 у int64.
В-третьих, у вас int 32-разрядный, используйте long или long long.

когда и для чего вообще может понадобиться конвертнуть UID в int

Для оптимизации вычислений и хранения.
Современные процессоры могут сравнивать 64-разрядные (А некоторые и больше) целые числа за одну инструкцию, когда каждое число имеет вот столько вариантов (Считай уникальных ID): 9223372036854775807 * 2 (Очень много короче).
Для сравнения строк, которые в читабельном виде представлять данное число комбинаций, нам потребуется значительно больше инструкций (Сравниваем строку по кускам - символ за символом (Всего 20 символов), каждое сравнение требует вычислений). При этом, т. к. мы используем читабельный вид строки, то мы ограничены 10 вариантами из 255(256) для каждого символа (4% от возможного), что, согласитесь, не эффективно.
Все это конечно можно ускорить: сравнивая сразу несколько символов (Что бы заполнить все 64-разряда, но это не вся строка) или использовать инструкции SIMD (Single Instruction, Multiple Data) (Тот же AVX), но во-первых, их не все процессоры поддерживают, а во-вторых, при их использовании, зачастую, повышается тепловыделение.
Получается 8 байт в int64 против 20 байт в string.
По факту UID в типе string нужен только для того, что бы ПОЛЬЗОВАТЕЛЬ мог его понять и что-то с ним сделать, т. к. в арме для любых чисел используется float из-за чего мы не можем весь UID представить точно в числе
Наглядный пример: steam - он хранит ID пользователя как 64-разрядное целое (из которых для ID используется всего 31 разряд, но не суть):
Прикрепленный файл  3.png   23.23К   0 Количество загрузок:

PS Если сомневаетесь в разнице (А она колоссальная), пишите, скину дизассемблированый код имитирующий сравнение двух ID представленных в типе int64 и string

Сообщение отредактировал vlad333000: 22 March 2019 - 00:27

  • 0

#13 OFFLINE   ReXcOr

ReXcOr

    Ст.сержант

  • Пользователи
  • 264 сообщений
  • Откуда:Moscow

Отправлено 22 March 2019 - 01:22

 

64 бит система, Windows
Выводы делаем сами.
attachicon.gifscreenday_01.jpg

Во-первых, в вашем примере тип double (double precision float point), когда арма использует float (single precision float point)
Во-вторых, минимальное и максимальное число для числа с плавающей точкой определяется как max/min мантиссы умноженное на основание с максимальной степенью, что даже для одинарной точности - число с 127 нулями, что больше, чем 64-разрядное целое.
Важно не макс/мин, а кол-во знаков которые могут быть точно представлены, что примерно: 7 (float) и 15 (double) десятичных разрядов, что меньше чем 9 у int32 и 20 у int64.
В-третьих, у вас int 32-разрядный, используйте long или long long.

когда и для чего вообще может понадобиться конвертнуть UID в int

Для оптимизации вычислений и хранения.
Современные процессоры могут сравнивать 64-разрядные (А некоторые и больше) целые числа за одну инструкцию, когда каждое число имеет вот столько вариантов (Считай уникальных ID): 9223372036854775807 * 2 (Очень много короче).
Для сравнения строк, которые в читабельном виде представлять данное число комбинаций, нам потребуется значительно больше инструкций (Сравниваем строку по кускам - символ за символом (Всего 20 символов), каждое сравнение требует вычислений). При этом, т. к. мы используем читабельный вид строки, то мы ограничены 10 вариантами из 255(256) для каждого символа (4% от возможного), что, согласитесь, не эффективно.
Все это конечно можно ускорить: сравнивая сразу несколько символов (Что бы заполнить все 64-разряда, но это не вся строка) или использовать инструкции SIMD (Single Instruction, Multiple Data) (Тот же AVX), но во-первых, их не все процессоры поддерживают, а во-вторых, при их использовании, зачастую, повышается тепловыделение.
Получается 8 байт в int64 против 20 байт в string.
По факту UID в типе string нужен только для того, что бы ПОЛЬЗОВАТЕЛЬ мог его понять и что-то с ним сделать, т. к. в арме для любых чисел используется float из-за чего мы не можем весь UID представить точно в числе
Наглядный пример: steam - он хранит ID пользователя как 64-разрядное целое (из которых для ID используется всего 31 разряд, но не суть):
attachicon.gif3.png

PS Если сомневаетесь в разнице (А она колоссальная), пишите, скину дизассемблированый код имитирующий сравнение двух ID представленных в типе int64 и string

 

В разнице я вооообще не сомневаюсь, ни разу, тк недавно приходилось работать со строками (сканировал в строке присутствие определенного слова и удалял), конвертить их в чарКод, тк кириллица очень хреного селектиться в арме (с чем это связано, я конечно же не знаю)...

_charCyr = "буква" select [0,3];
_charLat = "letter" select [0,3];

_charCyr // "б " ШТО? простите, пробел? От куда он там? а где "ук"? наверное на трубе.
_charLat // "let" все ровно

Собственно, половину потенциала работы с кириллицей у нас уже отваливается казалось бы,
но тут мы можем перевести чар, в чарКод(вот и пошла нагрузка про которую говорит vlad333000), что я собственно и сделал, но я зачем-то отклонился от темы и суть не в этом
 
С интом и правда, понадобится гораздо меньше ресурсов, может даже в сотни раз, но именно в арме, я считаю, вопрос стоит не настолько остро и можно пренебречь этим (особенно, когда с UID ты работаешь исключительно в бд и командой isEqualTo)
 
А в таких сервисах как стим, такое не позволительно, как я могу только предположить, тк глубоких знаний в программировании у меня нет, скрипты онли)

Сообщение отредактировал ReXcOr: 22 March 2019 - 01:39

  • 0

#14 OFFLINE   vlad333000

vlad333000

    Полковник

  • Пользователи
  • 3224 сообщений
  • Откуда:Кострома

Отправлено 22 March 2019 - 02:00

ReXcOr, 4 символа потому что арма для строк использует кодировку Unicode (В частности UTF8 )
В этой кодировке все латинские символы и большинство часто используемых знаков (Пробел, скобки, точки и т. п.) представлены одним байтом, который обозначает яисло от 0 до 127 - все они соотносяться с таблицей ASCII.
Символы других языков и все другие кодируются немного по другому: исспользуется сразу несколько байт (Их еще называют октетами). Кол-во байт определяется непрерывным кол-вом единиц в старших разрядах первого байта:


110xxxxx // 2 байта
1110xxxx // 3 байта
11110xxx // 4 байта
Все посследующие байты в посследовательности начинаются с:
10xxxxxx
Далее код символа заполняется с младшихдо старш разрядов, лишне биты заполняются 0.

Возьмем букву "А":
В юникоде она записана двумя байтами, соответственно начало будет следующим:
110xxxxx 10xxxxxx
Далее нам нужен код символа - 0x410:
11010000 10010000
Или просто 0xd090 - можете проверить.

Большинство функций ожидают char, но представление string - UTF-8
Вы выбрали 3 char = 3 байта
1 и 2 байт - обозначают "б", оставшийся 3 - неведомую дичь, т. к. символ UTF-8 не закончен, а т. к. в арме не для всех символов есть шрифт, то все левые символы обозначаются пробелами
Точнее не невидимую дичь, а символ 0xFFFD, который называется "REPLACEMENT CHARACTER" (�) и вставляется тогда, когда не удалось представить символ

Сообщение отредактировал vlad333000: 22 March 2019 - 02:25

  • 1

#15 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 22 March 2019 - 02:14

 

Современные процессоры могут сравнивать 64-разрядные (А некоторые и больше) целые числа за одну инструкцию, когда каждое число имеет вот столько вариантов (Считай уникальных ID): 9223372036854775807 * 2 (Очень много короче).

Давайте по сути. О чём разговор? Вычислять позиции в каждом фрейме или тупо найти в списке, при ините того же перса, нужного?

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

В остальном, какой смысл в арме в тех же числах длинной в добрый double, ибо даже 64 битность реал виртуалити под арму собственно то же виртуальна, то есть не реальных 64 бит, и это не мои фантазии а заявление самих бесов, они так и сказали про свои 64 бит, это наша магия, что на нормальном русском, через жопу).


 

Во-первых, в вашем примере тип double (double precision float point), когда арма использует float (single precision float point)
Во-вторых, минимальное и максимальное число для числа с плавающей точкой определяется как max/min мантиссы умноженное на основание с максимальной степенью, что даже для одинарной точности - число с 127 нулями, что больше, чем 64-разрядное целое.
Важно не макс/мин, а кол-во знаков которые могут быть точно представлены, что примерно: 7 (float) и 15 (double) десятичных разрядов, что меньше чем 9 у int32 и 20 у int64.

Я не настолько дикий что бы мне объяснять что такое числа с плавающей точкой). Мой скрин по сути о том сколько вообще имеет знаков число определённого типа в Windows.

 

В той же графике, того же самого флоат становится не хватать буквально не далеко в плане точности при вычислениях.

Я с такой байдой столкнулся вообще на банальной вещи, нужно было делать расчёт таймера в каждом фрейме. Я сначала ни хера не понял почему мой алгоритм не делал что должен делать и не вызывал ошибки, позже выяснилась банальная вещь, результат расчёта просто не умещался в флоат, то есть получаемое значение имело такую малую величину что тип флоат тупо превращал полученное значение в 0, double решил все проблемы.

 

 

В-третьих, у вас int 32-разрядный, используйте long или long long.

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

Если нужно хранить число больше int, то естественно и используем требуемый значению тип.

То есть, если вам нужно хранить число 100, и вы выбрали для хранения тип float, то эта переменная и займёт именно столько памяти сколько требуется типу, типу а не числу 100. То есть, по факту данная переменная зарезервирует себе памяти которой она не будет ни сколько не использовать.

 

 

ЗЫ

Да и даже тип float в скриптах юзается в урезаном виде, при определённых значениях движок для скриптовой системы урезает кол-во знаков, чем уменьшает точность числа естественно.


Сообщение отредактировал SteelRat: 22 March 2019 - 02:39

  • 0

#16 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 22 March 2019 - 02:49

Ну и собственно с чего всё началось)

 

Всем привет, подскажите как длинный номер показать в hint без искажения ?

И всё)

 

Ну а если ваш геймплей требует безостановочного перетрахивания массивов строк, бубен в руки)

 

И как правильно выразился AVI своём уроке

ArmA Scripting Tutorials: Как Найти Строку Внутри Строки

правильные пацаны делают всё правильно)

Пожалуйста Войдите или Зарегистрируйтесь чтобы увидеть скрытое содержание

в 76 раз быстрее, чем функция КК, и в 290 раз быстрее БИСовской. Это вам не в чешки срать!


Сообщение отредактировал SteelRat: 22 March 2019 - 02:57

  • 0

#17 OFFLINE   vlad333000

vlad333000

    Полковник

  • Пользователи
  • 3224 сообщений
  • Откуда:Кострома

Отправлено 22 March 2019 - 02:52

Для того и существую типы данных, что бы без нужды не занимать память пустыми данными. Если нужно хранить число больше int, то естественно и используем требуемый значению тип. То есть, если вам нужно хранить число 100, и вы выбрали для хранения тип float, то эта переменная и займёт именно столько памяти сколько требуется типу, типу а не числу 100. То есть, по факту данная переменная зарезервирует себе памяти которой она не будет ни сколько не использовать.

Я то знаю это, просто вы его упомянули в том выводе, с припиской Windows x64, было бы более уместно также вывести и 64-разрядный int. После чего второй собеседник написал следующее:

Собственно, UID в int не вместится, так что - string ))

Поэтому я и акцентировал внимание на этом, что не уместится в 32-разрядный, но в 64-разрядный - с лихвой

Давайте по сути. О чём разговор? Вычислять позиции в каждом фрейме или тупо найти в списке, при ините того же перса, нужного?

Спросили в чем соль переводить ID из string в int, вот я и ответил :)
А то, что арма это тот еще кусок... и так всем ясно

Я с такой байдой столкнулся вообще на банальной вещи, нужно было делать расчёт таймера в каждом фрейме. Я сначала ни хера не понял почему мой алгоритм не делал что должен делать и не вызывал ошибки, позже выяснилась банальная вещь, результат расчёта просто не умещался в флоат, то есть получаемое значение имело такую малую величину что тип флоат тупо превращал полученное значение в 0, double решил все проблемы.

На каком языке? Просто если C/C++ то там есть библиотеки timer.h/chrono, в которых определены функция для получения времени с точностью до наносекунд, без потери точности в миллионах секунд прошедших с начала отсчета времени (Так же аналог обычно есть и в других языках)
  • 0

#18 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 22 March 2019 - 03:07

Не проблема в языке, а как раз в использовании в вычислениях требуемого ситуации типа.

Просто когда я писал код я не ожидал на сколько малыми будут значения.

 

 

Поэтому я и акцентировал внимание на этом, что не уместится в 32-разрядный, но в 64-разрядный - с лихвой

По сути, мне так кажется, что сама скриптовая система и завязана, изначально естественно, именно на 32 бит, от сюда и растут ноги всяких граблей сегодня.


Сообщение отредактировал SteelRat: 22 March 2019 - 03:09

  • 0

#19 OFFLINE   vlad333000

vlad333000

    Полковник

  • Пользователи
  • 3224 сообщений
  • Откуда:Кострома

Отправлено 22 March 2019 - 03:26

SteelRat, проблема не сколько в скриптовой системе, сколько в остальном движке.
Для скриптинга перейти с 32 на 64 не составит большого труда, даже при использовании 32 архитектуры - современный компиляторы спокойно справляются с генерацией кода для работы с 64/128 разрядами на 32 архитектуре (Да даже умудряются 64 целые и double считать на 16 архитектуре без поддержки блока для расчета чисел с плавающей точкой - лично на себе проверил).
Минусы такого перехода: слегка уменьшенная производител ность (что и так для тормознутых скриптов не кретично) ну и несовместимость со старыми сейвамми

Сообщение отредактировал vlad333000: 22 March 2019 - 03:28

  • 0

#20 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 22 March 2019 - 05:45

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

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


 

Для скриптинга перейти с 32 на 64

БЕСы из чего угодно талантливы делать проблему)


  • 0




Яндекс.Метрика