Почему math.ceil(14.0)=14, а math.ceil(15.0)=16?

Страницы: 1
RSS
Почему math.ceil(14.0)=14, а math.ceil(15.0)=16?, Как вы округляете в большую/меньшую сторону, с заданным количеством десятичных знаков?
 
Добрый день.
Заметил странность в работе math.ceil().
Почему math.ceil(14.0)=14, а math.ceil(15.0)=16?

Для выставления цены с заданным количеством знаков после запятой, использую округление:
Код
function round_step_price(price, ty)
    local x=0
    if (ty=="sell") -- Продаем ->округлить в бОльшую сторону
        x= math.ceil(price/options.price_step) * options.price_step
    else -- Покупаем - округлим в меньшую сторону
        x= math.floor(price/options.price_step) * options.price_step
    end
    return x*1
end

Задача, при шаге цены 0.1, для продаж округлять так: 1.400 ->1.4, 1.4001 ->1.5, и так же 1.50->1.5, 1.50001->1.6. Но мой код, не работает, как ожидалось.

Как вы округляете в большую/меньшую сторону, с заданным количеством десятичных знаков?
 
В мире финансов принято работать с целыми числами. Именно по причине ошибок арифметики с плавающей точкой. Для примера https://ec.europa.eu/economy_finance/publications/pages/publication1224_en.pdf
Чаще всего это делают приводя число к целому виду (числу пунктов), так называемый decimal type.

Для примера, цена 145.53 при шаге 0.1, должна быть приведена либо к 145.50 или к 145.60.
Значит в пунктах наша цена = 14553, шаг 10.

Тогда можно взять остаток от деления 14553%10 = 3. И если он меньше некого порога, например 5, то вычитаем его 14553 - 3 = 14550.
А если больше, для примера 14558%10 = 8, то прибавляем 14553 - 8 + 10 = 14560

Точная цена - это полученное число, обратно приведенное к разрядности. В данном примере это / 100.

Но это просто один из вариантов.
 
Ну math.ceil(15.0) конечно не равен 16. Но если это результат вычисления, и там на самом деле не 15.0, а 15.0000000000000001 тогда да,  будет 16.
Проблема в том, что десятичные дроби не могут быть точно представлены, если только знаменатель не степень двойки. В частности, шаг цены 0.1:
Код
> return string.format("%1.18f",0.1)
0.100000000000000006
И да, единственный способ избежать ошибок округления - работать с целыми числами.
 
Цитата
Сергей написал:
Добрый день.
Заметил странность в работе math.ceil().
Почему math.ceil(14.0)=14, а math.ceil(15.0)=16?

Для выставления цены с заданным количеством знаков после запятой, использую округление:
Код
   function   round_step_price (price, ty)
     local  x =  0 
     if  (ty =  =  "sell" )  -- Продаем ->округлить в бОльшую сторону 
        x =   math.ceil (price/options.price_step)  *  options.price_step
     else   -- Покупаем - округлим в меньшую сторону 
        x =   math.floor (price/options.price_step)  *  options.price_step
     end 
     return  x *  1 
 end 

  
Задача, при шаге цены 0.1, для продаж округлять так: 1.400 ->1.4, 1.4001 ->1.5, и так же 1.50->1.5, 1.50001->1.6. Но мой код, не работает, как ожидалось.

Как вы округляете в большую/меньшую сторону, с заданным количеством десятичных знаков?
Если правильно понят, то вот пример.
Код
local step=0.1;
local p=1.2; while 2>p do  p=p+0.01;
local price=p-(p % step); 
price1=price price2=price
if p-price>0 then p1=p+0.1; price1=p1-(p1%step); p1=p-0.1; price2=p1-(p1%step);  end
print(p,price1, price2)
end

результат:
Код
1.21   1.3   1.1
1.22   1.3   1.1
1.23   1.3   1.1
1.24   1.3   1.1
1.25   1.3   1.1
1.26   1.3   1.1
1.27   1.3   1.1
1.28   1.3   1.1
1.29   1.3   1.1
1.3   1.4   1.1
1.31   1.4   1.2
1.32   1.4   1.2
1.33   1.4   1.2
1.34   1.4   1.2
1.35   1.4   1.2
1.36   1.4   1.2
1.37   1.4   1.2
1.38   1.4   1.2
1.39   1.4   1.2
1.4   1.4   1.4
1.41   1.5   1.3
1.42   1.5   1.3
1.43   1.5   1.3
1.44   1.5   1.3
1.45   1.5   1.3
1.46   1.5   1.3
1.47   1.5   1.3
1.48   1.5   1.3
1.49   1.5   1.3
1.5   1.6   1.4
1.51   1.6   1.4
1.52   1.6   1.4
1.53   1.6   1.4
1.54   1.6   1.4
1.55   1.6   1.4
1.56   1.6   1.4
1.57   1.6   1.4
1.58   1.6   1.4
1.59   1.6   1.4
1.6   1.7   1.5
1.61   1.7   1.5
1.62   1.7   1.5
1.63   1.7   1.5
1.64   1.7   1.5
1.65   1.7   1.5
1.66   1.7   1.5
1.67   1.7   1.5
1.68   1.7   1.5
1.69   1.7   1.5
1.7   1.8   1.6
1.71   1.8   1.6
1.72   1.8   1.6
1.73   1.8   1.6
1.74   1.8   1.6
1.75   1.8   1.6
1.76   1.8   1.6
1.77   1.8   1.6
1.78   1.8   1.6
1.79   1.8   1.6
1.8   1.9   1.7
1.81   1.9   1.7
1.82   1.9   1.7
1.83   1.9   1.7
1.84   1.9   1.7
1.85   1.9   1.7
1.86   1.9   1.7
1.87   1.9   1.7
1.88   1.9   1.7
1.89   1.9   1.7
1.9   2.0   1.8
1.91   2.0   1.8
1.92   2.0   1.8
1.93   2.0   1.8
1.94   2.0   1.8
1.95   2.0   1.8
1.96   2.0   1.8
1.97   2.0   1.8
1.98   2.0   1.8
1.99   2.0   1.8
2.0   2.1   1.9
Страницы: 1
Читают тему
Наверх