Информация об изменениях

Сообщение Re[7]: [забыл математику] Оптимизация алгоритма от 16.09.2022 19:38

Изменено 16.09.2022 19:39 xma

Re[7]: [забыл математику] Оптимизация алгоритма
Здравствуйте, Xander Zerge, Вы писали:

XZ>Ты свой туда же подложи, и посмотрим, это код не работает,

я согласен что мой код слегка чаще выдаёт — отличный от идеального результат, и что у Serge_Novikoff — оптимальнее код ..

но, также как и в моём коде из за проблем точности, также и в коде Serge_Novikoff — нередко возникает неверный (точнее не идеальный) результат (при чём весьма часто именно тот же неверный что и мой код выдаёт) ..

XZ>или ты просто эксплойтишь ограниченное количество знаков после точки в decimal.


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

XZ>Так-то шагов цены в виде периодической бесконечной дроби не бывает. Даже в крипте с меняющимся шагом.


ну как правильно говорит Xander Zerge — тут возможно стоит если нужна точность смотреть в сторону напр., "BigInteger" и тому подобных (которые обычно используют для банковских операций, для того чтобы не терять точность на float'ах или даже double'ах)

(могу предположить что в виде fixed point)

вот код рандома с моими test_optimal (и test_optimal2), если уж тебе так интересно по тестить ..

  Скрытый текст
https://dotnetfiddle.net/
using System;
                    
public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
        
        /*
        decimal marketBuyPrice = 5518.48m, overwriteMinStep = 55.184799999999999999999999999m;
        var ret = test_original(marketBuyPrice, overwriteMinStep);
        
        var ret_opt = test_optimal(marketBuyPrice, overwriteMinStep);
        var ret_opt2 = test_optimal2(marketBuyPrice, overwriteMinStep);
        
        var ret_opt_Serge_Novikoff = test_optimal_Serge_Novikoff(marketBuyPrice, overwriteMinStep);
        
        Console.WriteLine("marketBuyPrice = " + marketBuyPrice + ", overwriteMinStep = " + overwriteMinStep);
        Console.WriteLine("ret_original = " + ret);
        
        Console.WriteLine("ret_opt = " + ret_opt);
        Console.WriteLine("ret_opt2 = " + ret_opt2);
        
        Console.WriteLine("ret_opt_Serge_Novikoff = " + ret_opt_Serge_Novikoff);
        
        bool flag = (ret == ret_opt) && (ret == ret_opt2) && (ret == ret_opt_Serge_Novikoff) ;
        */
        
        ///*
        Random rand = new Random();
        
        bool flag = true;
        
        for (int i=0; i<10000; i++) {
            
            decimal marketBuyPrice = rand.Next(0, 1000000) / 100.0m; 
            decimal overwriteMinStep = rand.Next(1, 10000000) / 100.0m; 
            
            if (marketBuyPrice / overwriteMinStep > 100)
                overwriteMinStep *= marketBuyPrice / (overwriteMinStep * 100.0m);
            
            var ret = test_original(marketBuyPrice, overwriteMinStep);
            var ret_opt = test_optimal(marketBuyPrice, overwriteMinStep);
            var ret_opt2 = test_optimal2(marketBuyPrice, overwriteMinStep);
            
            var ret_opt_Serge_Novikoff = test_optimal_Serge_Novikoff(marketBuyPrice, overwriteMinStep);
            
            if ( ret != ret_opt || ret != ret_opt2 || ret != ret_opt_Serge_Novikoff ) {
            //if ( ret != ret_opt_Serge_Novikoff ) {
                
                Console.WriteLine("");
                Console.WriteLine("marketBuyPrice = " + marketBuyPrice + ", overwriteMinStep = " + overwriteMinStep);
                
                Console.WriteLine("ret_original = " + ret);
                Console.WriteLine("ret_opt = " + ret_opt);
                Console.WriteLine("ret_opt2 = " + ret_opt2);
                
                Console.WriteLine("ret_opt_Serge_Novikoff = " + ret_opt_Serge_Novikoff);
                
                flag = false;
            }
        }
        //*/
        
        Console.WriteLine("flag = " + flag);
    }
    
    public static decimal test_original(decimal marketBuyPrice, decimal overwriteMinStep)
    {        
        decimal mediumPrice2 = 0;

        do
        {
            mediumPrice2 += overwriteMinStep;
        } while (mediumPrice2 < marketBuyPrice);
        
        return mediumPrice2;
    }
    
    public static decimal test_optimal(decimal marketBuyPrice, decimal overwriteMinStep)
    {
        if (decimal.Zero == marketBuyPrice) // == 0
            return overwriteMinStep;
        
        decimal temp_remainder = marketBuyPrice % overwriteMinStep;
        
        if (decimal.Zero == temp_remainder) // == 0
            return marketBuyPrice;
        
        decimal mediumPrice2 = (decimal.Floor(marketBuyPrice / overwriteMinStep) + 1) * overwriteMinStep;
        return mediumPrice2;
    }
    
    public static decimal test_optimal2(decimal marketBuyPrice, decimal overwriteMinStep)
    {        
        if (decimal.Zero == marketBuyPrice) // == 0
            return overwriteMinStep;

        decimal mediumPrice2 = (decimal.Floor(marketBuyPrice / overwriteMinStep) + 1) * overwriteMinStep;
        
        if ( mediumPrice2 == marketBuyPrice + overwriteMinStep )
            mediumPrice2 -= overwriteMinStep;
            
        return mediumPrice2;
    }
    
    public static decimal test_optimal_Serge_Novikoff(decimal marketBuyPrice, decimal minStep)
    {        
        //if (decimal.Zero == marketBuyPrice) // == 0
        //    return overwriteMinStep;
        
        var imin = (int)(marketBuyPrice / minStep);
        
        if (minStep * imin < marketBuyPrice)
            ++imin;

        decimal mediumPrice2 = minStep * imin;
            
        return mediumPrice2;
    }
}
Re[7]: [забыл математику] Оптимизация алгоритма
Здравствуйте, Xander Zerge, Вы писали:

XZ>Ты свой туда же подложи, и посмотрим, это код не работает,

я согласен что мой код слегка чаще выдаёт — отличный от идеального результат, и что у Serge_Novikoff — оптимальнее код ..

но, также как и в моём коде из за проблем точности, также и в коде Serge_Novikoff — нередко возникает неверный (точнее не идеальный) результат (при чём весьма часто именно тот же неверный что и мой код выдаёт) ..

XZ>или ты просто эксплойтишь ограниченное количество знаков после точки в decimal.


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

XZ>Так-то шагов цены в виде периодической бесконечной дроби не бывает. Даже в крипте с меняющимся шагом.


ну как правильно говорит Xander Zerge — тут возможно стоит если нужна точность смотреть в сторону напр., (условного) "BigInteger" и тому подобных (которые обычно используют для банковских операций, для того чтобы не терять точность на float'ах или даже double'ах)

(могу предположить что в виде fixed point)

вот код рандома с моими test_optimal (и test_optimal2), если уж тебе так интересно по тестить ..

  Скрытый текст
https://dotnetfiddle.net/
using System;
                    
public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
        
        /*
        decimal marketBuyPrice = 5518.48m, overwriteMinStep = 55.184799999999999999999999999m;
        var ret = test_original(marketBuyPrice, overwriteMinStep);
        
        var ret_opt = test_optimal(marketBuyPrice, overwriteMinStep);
        var ret_opt2 = test_optimal2(marketBuyPrice, overwriteMinStep);
        
        var ret_opt_Serge_Novikoff = test_optimal_Serge_Novikoff(marketBuyPrice, overwriteMinStep);
        
        Console.WriteLine("marketBuyPrice = " + marketBuyPrice + ", overwriteMinStep = " + overwriteMinStep);
        Console.WriteLine("ret_original = " + ret);
        
        Console.WriteLine("ret_opt = " + ret_opt);
        Console.WriteLine("ret_opt2 = " + ret_opt2);
        
        Console.WriteLine("ret_opt_Serge_Novikoff = " + ret_opt_Serge_Novikoff);
        
        bool flag = (ret == ret_opt) && (ret == ret_opt2) && (ret == ret_opt_Serge_Novikoff) ;
        */
        
        ///*
        Random rand = new Random();
        
        bool flag = true;
        
        for (int i=0; i<10000; i++) {
            
            decimal marketBuyPrice = rand.Next(0, 1000000) / 100.0m; 
            decimal overwriteMinStep = rand.Next(1, 10000000) / 100.0m; 
            
            if (marketBuyPrice / overwriteMinStep > 100)
                overwriteMinStep *= marketBuyPrice / (overwriteMinStep * 100.0m);
            
            var ret = test_original(marketBuyPrice, overwriteMinStep);
            var ret_opt = test_optimal(marketBuyPrice, overwriteMinStep);
            var ret_opt2 = test_optimal2(marketBuyPrice, overwriteMinStep);
            
            var ret_opt_Serge_Novikoff = test_optimal_Serge_Novikoff(marketBuyPrice, overwriteMinStep);
            
            if ( ret != ret_opt || ret != ret_opt2 || ret != ret_opt_Serge_Novikoff ) {
            //if ( ret != ret_opt_Serge_Novikoff ) {
                
                Console.WriteLine("");
                Console.WriteLine("marketBuyPrice = " + marketBuyPrice + ", overwriteMinStep = " + overwriteMinStep);
                
                Console.WriteLine("ret_original = " + ret);
                Console.WriteLine("ret_opt = " + ret_opt);
                Console.WriteLine("ret_opt2 = " + ret_opt2);
                
                Console.WriteLine("ret_opt_Serge_Novikoff = " + ret_opt_Serge_Novikoff);
                
                flag = false;
            }
        }
        //*/
        
        Console.WriteLine("flag = " + flag);
    }
    
    public static decimal test_original(decimal marketBuyPrice, decimal overwriteMinStep)
    {        
        decimal mediumPrice2 = 0;

        do
        {
            mediumPrice2 += overwriteMinStep;
        } while (mediumPrice2 < marketBuyPrice);
        
        return mediumPrice2;
    }
    
    public static decimal test_optimal(decimal marketBuyPrice, decimal overwriteMinStep)
    {
        if (decimal.Zero == marketBuyPrice) // == 0
            return overwriteMinStep;
        
        decimal temp_remainder = marketBuyPrice % overwriteMinStep;
        
        if (decimal.Zero == temp_remainder) // == 0
            return marketBuyPrice;
        
        decimal mediumPrice2 = (decimal.Floor(marketBuyPrice / overwriteMinStep) + 1) * overwriteMinStep;
        return mediumPrice2;
    }
    
    public static decimal test_optimal2(decimal marketBuyPrice, decimal overwriteMinStep)
    {        
        if (decimal.Zero == marketBuyPrice) // == 0
            return overwriteMinStep;

        decimal mediumPrice2 = (decimal.Floor(marketBuyPrice / overwriteMinStep) + 1) * overwriteMinStep;
        
        if ( mediumPrice2 == marketBuyPrice + overwriteMinStep )
            mediumPrice2 -= overwriteMinStep;
            
        return mediumPrice2;
    }
    
    public static decimal test_optimal_Serge_Novikoff(decimal marketBuyPrice, decimal minStep)
    {        
        //if (decimal.Zero == marketBuyPrice) // == 0
        //    return overwriteMinStep;
        
        var imin = (int)(marketBuyPrice / minStep);
        
        if (minStep * imin < marketBuyPrice)
            ++imin;

        decimal mediumPrice2 = minStep * imin;
            
        return mediumPrice2;
    }
}