Как убрать нуль после точки?

Страницы: 1 2 След.
RSS
Как убрать нуль после точки?, .0
 
Допустим получаю значение цены через OnAllTrade. Далее пишу это значение в файл или таблицу - получается 77934.0
Как сделать, что бы была обычная запись 77934, без .0 ? Только недавно перешел с 32б QUIK, в 64b. В старом такого не было.
 
Вот так можно
Код
function round(num, n) -- Функция округляет до указанного количества знаков
   local n = (n or 0)
   return tonumber(string.format("%."..n.."f", num))
end
 
> math.floor(77934.0)
77934
 
Про string.format понял, работает, но сложно как то получается.

Про math.floor можно для чайника разжевать.
Как сделать проще простую операцию:
function OnAllTrade(alltrade)
price = tonumber(alltrade.price);

Далее я просто записываю в файл:
f:write(" "..price.."\n");

Как проще при этом использовать math.floor? Я похоже не понимаю синтаксис и поиск не помогает. (
 
Цитата
Алексей написал:
Про string.format понял, работает, но сложно как то получается.

Про math.floor можно для чайника разжевать.
Как сделать проще простую операцию:
function OnAllTrade(alltrade)
price = tonumber(alltrade.price);

Далее я просто записываю в файл:
f:write(" "..price.."\n");

Как проще при этом использовать math.floor? Я похоже не понимаю синтаксис и поиск не помогает. (
Наверное я не так понял (думал просто от нуля нужно избавиться). floor округляет вниз. Естественно, оно обнулит и не только нули.
 
Цитата
Алексей написал:
Про string.format понял, работает, но сложно как то получается.

Про math.floor можно для чайника разжевать.
Как сделать проще простую операцию:
function OnAllTrade(alltrade)
price = tonumber(alltrade.price);

Далее я просто записываю в файл:
f:write(" "..price.."\n");

Как проще при этом использовать math.floor? Я похоже не понимаю синтаксис и поиск не помогает. (
попробуйте так:
-------------------
function OnAllTrade(alltrade)
local price = alltrade.price;
f:write(price.."\n");
 
 
Цитата
nikolz написал:
Цитата
Алексей написал:
Про string.format понял, работает, но сложно как то получается.

Про math.floor можно для чайника разжевать.
Как сделать проще простую операцию:
function OnAllTrade(alltrade)
price = tonumber(alltrade.price);

Далее я просто записываю в файл:
f:write(" "..price.."\n");

Как проще при этом использовать math.floor? Я похоже не понимаю синтаксис и поиск не помогает. (
попробуйте так:
-------------------
function OnAllTrade(alltrade)
local price = alltrade.price;
f:write(price.."\n");
К сожалению так не работает. Записывается цена и .0 . Оно просто занимает место в таблице или файле, а таких значений много, что очень не удобно.
 
Порешаем вопрос радикальненько. Функция FormatPrice форматирует цену согласно справочнику инструментов, с правильным шагом цены и правильным числом знаков после запятой. Если цена указана не кратно шагу, она округляется по правилу "к ближайшему". Для неизвестных квику бумаг цена форматируется с 6 знаками после запятой.

Че делать по шагам:
1) рядом со своим скриптом создаем файл FormatPrice.lua
2) в него копипастим следующий код
Код
local defparams = { ['scale'] = 6, ['step'] = 0.000001 }
local strm = '-'
local stre = ''
local strf =
{
   [0] = '%s%u',
   [1] = '%s%u.%01u',
   [2] = '%s%u.%02u',
   [3] = '%s%u.%03u',
   [4] = '%s%u.%04u',
   [5] = '%s%u.%05u',
   [6] = '%s%u.%06u',
   [7] = '%s%u.%07u',
   [8] = '%s%u.%08u',
   [9] = '%s%u.%09u'
}
local pwr10 =
{
   [0] = 1,
   [1] = 10,
   [2] = 100,
   [3] = 1000,
   [4] = 10000,
   [5] = 100000,
   [6] = 1000000,
   [7] = 10000000,
   [8] = 100000000,
   [9] = 1000000000,
}
local seccache = {}

local function SecCacheMiss(classcode, seccode)
   local t = getSecurityInfo(classcode, seccode)
   if not t or not t.scale then
      return defparams
   end
   local tsec = seccache[seccode]
   if not tsec then
      tsec = {}
      seccache[seccode] = tsec
   end
   local tcls = tsec[classcode]
   if not tcls then
      tcls = { ['scale'] = t.scale, ['step'] = t.min_price_step }
      tsec[classcode] = tcls
   end
   return tcls
end

local function GetSecParams(classcode, seccode)
   local tsec = seccache[seccode]
   if not tsec then
      return SecCacheMiss(classcode, seccode)
   end
   local tcls = tsec[classcode]
   if not tcls then
      return SecCacheMiss(classcode, seccode)
   end
   return tcls
end

function FormatPrice(classcode, seccode, price)
   if nil == price then price = 0 end
   local prefix
   if price < 0 then
      prefix = strm
      price = math.abs(price)
   else
      prefix = stre
   end
   local sp = GetSecParams(classcode, seccode)
   local iprice, fprice = math.modf(math.floor(price / sp.step + 0.5) * sp.step)
   return string.format(strf[sp.scale], prefix, iprice, math.floor(fprice * pwr10[sp.scale] + 0.5))
end

function FormatPriceFlushCache()
   seccache = {}
end
3) в начале своего скрипта пишем
Код
require('FormatPrice')
4) где надо отформатировать цену, пишем
Код
string_price = FormatPrice(class_code, sec_code, price)
5) если скрипт не останавливается между сессиями, при возможном изменении справочников (т.е. в OnConnected или OnCleanUp) пишем
Код
FormatPriceFlushCache()
Последнее ничего не ломает, так что можно по желанию и чаще вызывать. Только смысла нет.
 
function string.trim_zeroes(num,precision)

return string.format("%.".. (precision or "8") .. "f",num):match("^([%-]?%d*%.-%d-)%.?0*$")
end

precision берем из getSecurityInfo или вообще не указываем, тогда все нули после запятой отрежутся
www.bot4sale.ru

Пасхалочка для Алексея Иванникова: https://forum.quik.ru/messages/forum10/message63088/topic7052/#message63088
 
Цитата
s_mike@rambler.ru написал:
тогда все нули после запятой отрежутся
А у зила шаг цены 5 )
 
Цитата
Anton написал:
Цитата
   s_mike@rambler.ru написал:
тогда все нули после запятой отрежутся
А у зила шаг цены 5 )
И?
www.bot4sale.ru

Пасхалочка для Алексея Иванникова: https://forum.quik.ru/messages/forum10/message63088/topic7052/#message63088
 
Цитата
s_mike@rambler.ru написал:
И?
Непорядочек. Ладно, с зилом это вроде шутки, но есть шаги и 0.02, и 0.0025 и еще какие-то, там будет совсем нехорошо.
 
Шаг цены не представляет никакого интереса в данном случае. Для precision (при необходимости) используется значение  scale из getSecurityInfo  
www.bot4sale.ru

Пасхалочка для Алексея Иванникова: https://forum.quik.ru/messages/forum10/message63088/topic7052/#message63088
 
Цитата
s_mike@rambler.ru написал:
Шаг цены не представляет никакого интереса в данном случае.
Звучит как предложение иметь особую функцию форматирования для каждого случая. Так тоже можно, конечно.
 
А нельзя просто отрезать нули после запятой к чертям собачьим с помощью string.sub?
 
Цитата
Владимир написал:
А нельзя просто отрезать нули после запятой к чертям собачьим с помощью string.sub?
Можно. Тогда следующий вопрос будет "я сделал как написано в этой ветке, теряется дробная часть у <подставить бумагу>".
 
Anton, С какой радости "теряется"? Вот навскидку алгоритм:
1. Ищем в строке точку (или что там - запятую?), если не нашли, возвращаем исходную строку.
2. В цикле по символам (не знаю, есть ли в Lua функция "забрать символ по индексу") проверяем символы "хвоста" на '0'
3. Если не равно - возвращаем исходную строку, если добежали до string.len - возвращаем огрызок до запятой.
 
Цитата
А нельзя просто отрезать нули после запятой к чертям собачьим с помощью string.sub?

price = price - price%1
 
Цитата
Владимир написал:
Вот навскидку алгоритм
Это техническая часть, как именно резать, вопрос в том, до скольких нулей резать. Выше само форматирование две строки занимает безо всяких циклов, все остальное там это кэш информации по бумагам, чтобы не дергать на каждом вызове getSecurityInfo. Если заранее известно, как обрезать, две строки и останется. Сделайте лучше, я будто против.
 
Цитата
Anton написал:
Код
if nil == price then price = 0 end
Плохая практика, имхо
Надо делать так, как надо. А как не надо - делать не надо.
 
Цитата
Старатель написал:
Плохая практика
Да, согласен. Надо убрать эту строчку.
 
Anton, Как это "сколько нулей резать"? Сколько есть, столько и резать!  :smile:  
 
a=77934.000
if a==math.floor(a) then a=math.floor(a) end

может так?
 
Цитата
Игорь написал:
a=77934.000
if a==math.floor(a) then a=math.floor(a) end

может так?
Да, это именно то, что надо! Спасибо!!!
 
Игорь, Обалдеть! Я было подумал, что при a=77934.12000 будет работать неправильно, но она чётко отрезала "хвостовые" нули, не задев дробную часть: 77934.12. Браво!  
 
Игорь, Украл к себе в виде функции - не работает, все нули на месте. Присобачил в начале tonumber - заработало.
 
Цитата
Владимир написал:
a=77934.12000
это само по себе выведется как 77934.12. floor() тут не причем.
 
Игорь, А кто тут при чём, если в коде кроме floor ваще ничего нет? :)
 
В руки бы насрать тому идиоту, который придумал тип данных var! Сначала у меня "тихо шифером шурша крыша едет не спеша" от таблицы визуализации, пока не прочитал здесь же, в ветке трёхлетней давности, что "для того, чтобы строки отображались, необходимо, чтобы вызов CreateWindow() производился ДО (!!!) процедуры добавления строк в таблицу", и что эта "особенность" не только не исправлена, но до сих пор даже не документирована! Теперь крыша едет от преобразования типов: я заглатываю исходную информацию из файла (там, естественно, строки) и распихиваю её по своим таблицам (а там уже и строки, и целочисленные поля, и поля с плавающей точкой). Но я ПОНЯТИЯ НЕ ИМЕЮ по каким соображениям она присваивает данные и передаёт аргументы какого-то типа. Если строки - ругается math.floor, если предварительно поставить s=tonumber(s) - ругается на этот оператор (вернее, возвращает nil). Я уже до ручки дошёл: перед вызовом функции обуваю аргумент в tostring, а внутри функции переворачиваю его в tonumber - пофиг: "attempt to concatenate a nil value (local 's')". И уж совсем прикол, что в  AddColumn тип данных столбца всё-таки УКАЗЫВАЕТСЯ: там тебе и QTABLE_STRING_TYPE, и QTABLE_INT_TYPE, и QTABLE_DOUBLE_TYPE, панимаш! Кто-нить знает, ЧТО этой скотине от меня надобно?!  :cry:  
 
Владимир, добрый день!

Не до конца поняли вашу проблему. Что вы хотите сделать и что конкретно не получается?
В таблицу необходимо отправлять тип данных, соответствующий типу данных столбца, в ячейку которого происходит вставка.
Лучше всего - приведите пример когда, на котором возникает ошибка.
 
Roman Azarov, Добрый день, Роман.

Я хочу знать, какой тип имеют мои данные или принудительно установить их в тип string - тем более, что, насколько я понимаю, ничего другого в Lua и нет. Я хочу, чтобы интерпретатор Lua выполнял мои команды, а не ругался нехорошими словами. С КАКОГО БОДУНА у него там в tonumber вдруг появляется nil, причём не всегда, а в любой момент, когда ему вздумается. Строки на вход ему подаются правильно - проверял, гарантирую!

Это смотря в какую таблицу! В описании языка "всё есть таблица", в реальности же никаких таблиц нет вообще, а есть дерево объектов вида key-value. Штука полезная, иногда, но и только.

А КАК, простите, я могу "в таблицу отправлять тип данных, соответствующий типу данных столбца, в ячейку которого происходит вставка", если у меня а) некоторых таких типов нет вообще б) я не имею возможности самостоятельно задать тип переменной и даже в) я не знаю, какой тип задал ей интерпретатор, причём г) я вовсе не уверен, что на следующем шаге цикла он не подставит ей какой-нибудь другой тип.

Да вот НЕ МОГУ Я "привести пример когда, на котором возникает ошибка". Ибо она возникает НЕ ВСЕГДА, а когда ей заблагорассудится. Ну вот, хотя бы тот код, который я украл у Игоря (к слову, я совершенно не понимаю, как работает его алгоритм и почему он вообще работает). Первый же оператор этой функции время от времени возвращает nil

function d0(s) -- обрезка концевых нулей после запятой
s=tonumber(s) -- для числовых переменных
if s==math.floor(s) then s=math.floor(s) end
return s -- возвращаем огрызок
end
 
Владимир, рекомендую прежде чем возмущаться, ознакомиться с учебниками по языку Lua, раз уж приходится на нём программировать в терминале. Также можно почитать информацию о динамически типизируемых языках и зачем так сделали их создатели.

Хотите узнать тип переменной -- есть функция type(переменная), которая возвращает строку с названием типа.

Если tonumber возвращает nil, значит аргумент не может быть представлен в виде числа.

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

Винить кого-то в своих ошибках -- самый простой способ, конечно.
 
_sk_, Первое же, что я сделал - это именно "ознакомился с учебниками по языку Lua". Правда, очень бегло, ибо программирую я уже не один десяток лет - в том числе, и на "динамически типизируемых языках" и не устаю материться, "зачем так сделали их создатели".

Да не хочу я узнать тип переменной - мне нужно, чтобы она не меняла свой тип, когда интерпретатору моча в голову ударит! Что происходит в момент передачи этой переменной в качестве аргумента или присвоения - один Бог знает!

Я уже писал, что аргумент МОЖЕТ быть представлен в виде числа, и что я это специально ПРОВЕРЯЛ!

КОМУ "из логики приложения должно быть понятно, что именно туда записывается"? Вот фрагмент моего вчерашнего кода:

if a[i][5][0]~=0 then
 InsertRow(T,j);
 SetCell(T,j,0,a[i][1]);
 SetCell(T,j,2,d0(a[i][4]));
 SetCell(T,j,7,d0(a[i][5][1]));
 j=j+1
end;

Так вот: "по логике" a[i][1] у меня СТРОКА, i, j, [i][5][0] - ЦЕЛОЕ, a[i][4] и a[i][5][1] - ВЕЩЕСТВЕННЫЕ. Так КАКОГО ЖЕ ХРЕНА a[i][5][1], в котором содержится "16.4375" вдруг "не может быть представлен в виде числа"?
 
Цитата
Владимир написал:
а не хочу я узнать тип переменной - мне нужно, чтобы она не меняла свой тип,
В Lua, как и большинстве (или всех?) других языков, тип переменной произвольно не меняется. Тип может измениться только при определённых действиях над переменной. И опытный программист всегда знает, какой тип переменной будет при той или иной операции над переменной.
Надо делать так, как надо. А как не надо - делать не надо.
 
Цитата
Anton написал:
все остальное там это кэш информации
Кешировать степень числа (pwr10) не имеет смысла, т.к. возведение в степень быстрее в два раза, чем вытащить значение из таблицы.
А вот операции со строками в Lua на порядок дольше, т.ч. strf будет полезно.
Надо делать так, как надо. А как не надо - делать не надо.
 
Старатель, Ну вот Вы, лично Вы - опытный программист? Можете мне сказать, что этой гадине от меня требуется?  :smile: У меня вчера даже такой код давал ошибку:
SetCell(T,j,7,d0(tostring(a[i][5][1])));
 
Владимир, мой скил не так высок, чтобы по приведённому кусочку кода дать ответ
Надо делать так, как надо. А как не надо - делать не надо.
 
Старатель, Блин, ну если непосредственно перед вызовом функции стоит tostring, а первая же команда внутри функции tonumber, то КАКОЙ ЖЕ требуется "скилл", чтобы это объяснить?
 
Владимир, у меня нет навыка чтения мыслей.
В той строчке кода, что вы привели нет tonumber.
Вы можете привести полный код скрипта или продолжить возмущаться, но лучше не на этом форуме, т.к. тут общаются взрослые дяди  :lol:
Надо делать так, как надо. А как не надо - делать не надо.
 
Старатель, Код самой функции приведён выше, и взрослые дяди обычно читают ВСЮ всеку.
 
Всю ВЕТКУ.
 
Надо делать так, как надо. А как не надо - делать не надо.
 
Старатель, Некорректный пример - Вы передали в функцию не переменную, а значение. Более того: эта функция даёт ошибку НЕ ВСЕГДА, но вот на то, что я написал - давала.
 
Владимир,
То что ситуация повторяется не всегда, совершенно не значит что мы сможем разобраться по отдельным строкам кода.
Просьба привести полный пример кода на котором повторяется проблема, иначе разбор может затянуться на века.

Например, Вы знаете что  функция tonumber может принимать два параметра, а не один, и если случайно передать туда что попало во второй параметр, то тоже будет nil?
мы же не знаем что Вы туда передаете. ну "s" и что? а вдруг эта самая "s" и не "s" вовсе, а функция или еще что. Вот и получается что мы можем только гадать как у Вас там устроено, а Вы будете эти догадки отметать. И так по кругу пока воображения на догадки хватает.
 
В начало функции поставьте проверку на nil и выводите сообщение (через message, например, или в лог, если он у есть). При работе со вложенными массивами/таблицами часто бывает, что забыли внутренние структуры инициализировать.

Цитата
Я уже до ручки дошёл: перед вызовом функции обуваю аргумент в tostring, а  внутри функции переворачиваю его в tonumber - пофиг: "attempt to  concatenate a nil value (local 's')".

Тут же явно на nil намёк.

Можно ещё всё в xpcall завернуть и печатать стек, чтобы было понятно, откуда вы попали со значением nil. Пример, как это обычно делается в моём коде приведён ниже. При любой ошибке видно, где она произошла.
 
Код
    logger:info("STARTED")
    local status, errMessage = xpcall(function()
        if isConnected() ~= 1 then
            local msg = config.name .. " is not connected on start. Shutdown."
            logger:error(msg)
        else
            initialize()
            run()
        end
    end, function(err)
        logger:error(tostring(err))
        logger:error(debug.traceback())
    end)
    if not status and errMessage ~= nil then
        logger:error(errMessage)
    end
 
Я хренею, дорогая редакция! Запустил сейчас свой вчерашний скрипт - ошибок НЕТ, но и данных в таблице НЕТ! Клянусь - ни единого байта в коде не менял! В смысле, первая строчка (код тикера) выводится, а остальные - нет, пусто! Поставил tostring не [только] на входе, но и на выходе - заработало! Вот "мудифицированный!" код:

if a[i][5][0]~=0 then
 InsertRow(T,j);
 SetCell(T,j,0,a[i][1]);
 SetCell(T,j,2,tostring(d0(a[i][4])));
 SetCell(T,j,7,tostring(d0(tostring(a[i][5][1]))));
 j=j+1
end;

Я тут было подумал, что таблицу-то я в прерывании затирал (Clear), а потом заново формировал строки (InsertRow и т.д.), так что мне из-за такого "варварства" мог какой-нить "сборщик мусора" как-то гадить, но и сейчас я делаю именно так! Воистину "тихо шифером шурша"...  :shock:  
 
Sergey Gorokhov, Ну я ведь тоже не мальчик в программировании, а код у меня там сложный. АЛГОРИТМИЧЕСКИ сложный.

Нет, я не знаю, что "функция tonumber может принимать два параметра, а не один" (точнее, где-то читал, но тут же забыл - кажется, основание системы счисления от 2 до 36), но я-то передаю ОДИН параметр!

Вот я и говорю: что там за s - одному Богу известно! В смысле, интерпретатору. Я инициализирую переменные из строк файла, а что там в моей таблице получается - без понятия: я-то переменным присваиваю вроде как строки (результат string.sub), но по смыслу там в подавляющем большинстве записаны числа...
 
_sk_, Ну уж нет! Там у меня информация по тикерам сидит, обновляющаяся по прерываниям: цена последней сделки, объёмы сделок и цена покупки и т.д. Что мне толку от лога? Я лучше не буду забывать внутренние структуры инициализировать!  :smile:

Да, это даже не "на nil намёк", а сам nil собственной персоной!  :smile:  
 
Ха-ха-ха! А мой последний "шыдевр" ажно General Protection Fault схлопотал! Internal exception happened, панимаш, весь Квик вылетел! А всего-то написал:
SetCell(T,j,8,string.format("%1.2f",d0(a[i][4]/a[i][5][1]*100-100)));

А второй раз запустил - вроде, работает...  :smile:

Всё, всем спасибо, код буду чистить на свежую голову.  
 
Цитата
Алексей написал:
Цитата
nikolz написал:
 
Цитата
Алексей  написал:
Про string.format понял, работает, но сложно как то получается.

Про math.floor можно для чайника разжевать.
Как сделать проще простую операцию:
function OnAllTrade(alltrade)
price = tonumber(alltrade.price);

Далее я просто записываю в файл:
f:write(" "..price.."\n");

Как проще при этом использовать math.floor? Я похоже не понимаю синтаксис и поиск не помогает. (
 попробуйте так:
-------------------
function OnAllTrade(alltrade)
local price = alltrade.price;
f:write(price.."\n");
К сожалению так не работает. Записывается цена и .0 . Оно просто занимает место в таблице или файле, а таких значений много, что очень не удобно.
тогда так:
function OnAllTrade(alltrade)
local price = alltrade.price;
f:write(tostring(price).."\n");
Страницы: 1 2 След.
Читают тему
Наверх