Уважаемые разработчики и коллеги, может кто подскажет, почему результат разный и что надо подставить в string.format, чтобы он стал одинаковый? Как вы понимаете, необходимо, чтобы Номер заявки или сделки в виде строки всегда был нормальным числом, идентичным самому числу.
а можно подробнее про ошибку. у меня Lua 5.3 работает корректно вот пример: a=1952336732254970146 print(a) print(tostring(a)) print(a+1) print(tostring(a+1)) ------- результат: 1952336732254970146 1952336732254970146 1952336732254970147 1952336732254970147 ---------------- что не так?
Пользователь
Сообщений: Регистрация: 28.03.2016
14.09.2020 20:30:32
Цитата
nikolz написал: а можно подробнее про ошибку. у меня Lua 5.3 работает корректно вот пример: a=1952336732254970146 print(a) print(tostring(a)) print(a+1) print(tostring(a+1)) ------- результат: 1952336732254970146 1952336732254970146 1952336732254970147 1952336732254970147 ---------------- что не так?
Внимательно посмотрите все мои варианты и сделайте ваш пример для числа 9152336732254970146
- Роботы и индикаторы
Пользователь
Сообщений: Регистрация: 28.03.2016
14.09.2020 20:32:20
Цитата
Александр М написал: Пока получается, что лучше всего работает это:
Предлагаем быть более внимательным в передаче параметров в функцию. от куда у Вас возьмется параметр "x" если есть только переменная "a"?
Согласен, моя ошибка. Правда проблему не решило, если произошло изменение типа:
Код
local function tostringEX(x)
return tostring(math.tointeger(x) or x)
end
a=1952336732254970146.0
message(tostringEX(a).." "..tostring(a))
Результат: 1952336732254970112 1.952336732255e+18
Если изменения типа не было, то там и tostring() прекрасно работает.
- Роботы и индикаторы
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
15.09.2020 16:18:14
Цитата
Александр М написал: проблему не решило, если произошло изменение типа
При преобразовании в double произошла потеря точности. Первоначальное значение никакими ухищрениями уже не вернуть.
Код
a = 1952336732254970112
b = a + 0.0
print(a == b)
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 30.01.2015
Роботорговец
15.09.2020 16:23:25
Выше пример преобразования числа без потери точности (поэтому format с ним справляется) А это с потерей точности:
Код
a = 1952336732254970146
b = a + 0.0
print(a == b)
Надо делать так, как надо. А как не надо - делать не надо.
Пользователь
Сообщений: Регистрация: 27.01.2017
15.09.2020 16:25:47
Только сейчас увидел, что Вы пытаетесь сделать. lua не может преобразовать double с таким числом цифр как 9152336732254970146.0
4-ое издание Programming in Lua, глава 4 ()
For floating-point numbers, Standard Lua uses double precision. It represents each number with 64 bits, 11of which are used for the exponent. Double-precision floating-point numbers can represent numbers withroughly 16 significant decimal digits, in a range from -10308 to 10308. (Small Lua uses single-precisionfloats, with 32 bits. In this case, the range is from -1038 to 1038, with roughly seven significant decimaldigits.)
Any integer up to 2^53 (which is 9007199254740992) has an exact representation as a double-precisionfloating-point number. Integers with larger absolute values may lose precision when converted to a float.
Поэтому если число имеет тип math.type = integer, то до 2^53 (9007199254740992) нет проблем представления. А если это уже double, то его не будет.
Пользователь
Сообщений: Регистрация: 28.03.2016
15.09.2020 19:33:35
Цитата
Nikolay написал: Только сейчас увидел, что Вы пытаетесь сделать. lua не может преобразовать double с таким числом цифр как 9152336732254970146.0
4-ое издание Programming in Lua, глава 4 ( )
For floating-point numbers, Standard Lua uses double precision. It represents each number with 64 bits, 11of which are used for the exponent. Double-precision floating-point numbers can represent numbers withroughly 16 significant decimal digits, in a range from -10308 to 10308. (Small Lua uses single-precisionfloats, with 32 bits. In this case, the range is from -1038 to 1038, with roughly seven significant decimaldigits.)
Any integer up to 2^53 (which is 9007199254740992) has an exact representation as a double-precisionfloating-point number. Integers with larger absolute values may lose precision when converted to a float.
Поэтому если число имеет тип math.type = integer, то до 2^53 (9007199254740992) нет проблем представления. А если это уже double, то его не будет.
Специально я не пытаюсь, я боюсь, чтобы случайно преобразования не было, иначе беда. Причем, если она случилась, то она не лечится, номер изменится.
- Роботы и индикаторы
Пользователь
Сообщений: Регистрация: 30.01.2015
18.09.2020 07:39:07
Цитата
Александр М написал: print(a)print(tostring(a))print(a+1)print(tostring(a+1))
сделал так: а=9152336732254970146 print(a) print(tostring(a)) --------------------- результат: 9152336732254970146 9152336732254970146 ---------------- что не так?
сделал так: а=9152336732254970146 print(a) print(tostring(a)) --------------------- результат: 9152336732254970146 9152336732254970146 ---------------- что не так?
Пока тип не поменялся, все tostring() работает корректно, я выше уже написал. Теперь надо следить за этим в коде, т.к. если он изменится, то преобразование числа в строку дает или неправильное значение или вообще с e+... Выше я продемонстрировал. Я в своем коде проблему решил, просто проверил все места, где смотрится или преобразовывается номера заявок или сделок.
- Роботы и индикаторы
Пользователь
Сообщений: Регистрация: 30.01.2015
20.09.2020 08:04:01
Цитата
Александр М написал: В связи с переходом биржи мы дождались 19 знаков.
Уважаемые разработчики и коллеги, может кто подскажет, почему результат разный и что надо подставить в string.format, чтобы он стал одинаковый? Как вы понимаете, необходимо, чтобы Номер заявки или сделки в виде строки всегда был нормальным числом, идентичным самому числу.
Результат: "bad argument #2 to 'format' (number has no integer representation)"
Правильно я понял, что Вы где надо и не надо лепили к числам ".0" В итоге получали переполнение разрядной сетки мантиссы, т к в отличии от целого числа на нее в 64 битах меньше места? Ну батенька, надо учить мат.часть.
написал: В связи с переходом биржи мы дождались 19 знаков.
Уважаемые разработчики и коллеги, может кто подскажет, почему результат разный и что надо подставить в string.format, чтобы он стал одинаковый? Как вы понимаете, необходимо, чтобы Номер заявки или сделки в виде строки всегда был нормальным числом, идентичным самому числу.
Результат: "bad argument #2 to 'format' (number has no integer representation)"
Правильно я понял, что Вы где надо и не надо лепили к числам ".0" В итоге получали переполнение разрядной сетки мантиссы, т к в отличии от целого числа на нее в 64 битах меньше места? Ну батенька, надо учить мат.часть.
Не правильно, я вообще ничего не лепил и у меня преобразования не было, но я в коде исторически использовал "%.f", т.к. надеялся, что если преобразование типов случайно пройдет, то в строку не добавится ".0" в конце. Код .0 не добавлял, а вот сам номер изменил даже при преобразовании целого числа в строку, о чем я и написал.
Не правильно, я вообще ничего не лепил и у меня преобразования не было, но я в коде исторически использовал "%.f", т.к. надеялся, что если преобразование типов случайно пройдет, то в строку не добавится ".0" в конце. Код .0 не добавлял, а вот сам номер изменил даже при преобразовании целого числа в строку, о чем я и написал.
вот это "%.f" и есть преобразование из целого в вещественное. В документации сказано: Стандартный Lua использует 64-битные целые (integer) и вещественные числа двойной точности (double 64-bit) В итоге у Вас 64 битное целое не умещается в 64 битное вещественное, т к для мантиссы всего 53 бита Проблема решается если целое число преобразовать в вещественное расширенной точности (long double ), но луа не поддерживает данный формат, а железо поддерживает. Поэтому если надо, то пишите свою функцию на API C.
Касательно предложения в 10 вопросе tostring(math.tointeger(x) or x), попробуйте данное решение на числе tostring(math.tointeger(1.16*100) or 1.16*100) Увидите, что не работает.
Пользователь
Сообщений: Регистрация: 23.01.2015
24.09.2020 16:18:14
Nikolay, Допустим. А зачем делать арифметические операции с номером заявки/сделки?
Пользователь
Сообщений: Регистрация: 27.01.2017
24.09.2020 16:25:57
Не зачем, наверно. Но если использовать единый подход для форматирования, то он должен быть единым.
С другой стороны, не очень понятно зачем вообще применять форматирование для чисел типа integer. tostring итак их выводит корректно. Если только вы не гарантируете тип integer для номера заявки. Но тогда это будет уже другой разговор.
Пользователь
Сообщений: Регистрация: 23.01.2015
24.09.2020 16:39:35
Nikolay, Тема про "math.tointeger" возникла из-за появления ".0", к большим числам она не относится. Автор хотел исследовать вопрос и ему было предложено такое решение для ознакомления
Цитата
Nikolay написал: С другой стороны, не очень понятно зачем вообще применять форматирование для чисел типа integer. tostring итак их выводит корректно. Если только вы не гарантируете тип integer для номера заявки. Но тогда это будет уже другой разговор
применять форматирование не нужно, в той же ветке сказано что tostring будет работать с большими числами, собственно Вы и сами это говорили.
По сути, с числами есть две проблемы, первая это появление ".0" у любых чисел, и эта проблема чинится предложенной функцией. Вторая это некорректное преобразование 19ти значных дробных чисел в строку и решения для нее нет. Но в практике, 19 ти значные числа есть только в номерах заявок/сделок, а для них нет никаких практических задач которые могли бы привести к преобразованию их в дробное число.