Здравствуйте, Xander Zerge, Вы писали:
XZ>Ты свой туда же подложи, и посмотрим, это код не работает, или ты просто эксплойтишь ограниченное количество знаков после точки в decimal.
я решил задачу (test_optimal2), теперь верно абсолютно всегда — даже когда test_optimal_Serge_Novikoff неверно ..
я красавчег
P.S.: ещё один fix на сравнение с нулём
| source code (fix) |
| проверяй тут,
https://dotnetfiddle.net/
using System;
public class Program
{
// работоспособный минимум (на конкретных тестах) это (1 / Math.Pow(10, 24))
public static decimal DecimalEpsilon = (decimal) (1 / Math.Pow(10, 6));
public static void Main()
{
Console.WriteLine("Hello World");
/*
decimal marketBuyPrice = 736.72m, overwriteMinStep = 7.3671999999999999999999999999m;
////decimal marketBuyPrice = 0.000000001m, overwriteMinStep = 0.1m;
var ret = test_original(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_opt2 = " + ret_opt2);
Console.WriteLine("ret_opt_Serge_Novikoff = " + ret_opt_Serge_Novikoff);
bool flag_test_optimal2 = Math.Abs(ret - ret_opt2) < DecimalEpsilon ;
Console.WriteLine("flag_test_optimal2 = " + flag_test_optimal2);
bool flag_test_Serge_Novikoff = Math.Abs(ret - ret_opt_Serge_Novikoff) < DecimalEpsilon ;
Console.WriteLine("flag_test_Serge_Novikoff = " + flag_test_Serge_Novikoff);
*/
///*
Random rand = new Random();
bool flag_test_optimal2 = true;
bool flag_test_Serge_Novikoff = 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_opt2 = test_optimal2(marketBuyPrice, overwriteMinStep);
var ret_opt_Serge_Novikoff = test_optimal_Serge_Novikoff(marketBuyPrice, overwriteMinStep);
bool temp_flag_test_optimal2 = Math.Abs(ret - ret_opt2) < DecimalEpsilon;
bool temp_flag_test_Serge_Novikoff = Math.Abs(ret - ret_opt_Serge_Novikoff) < DecimalEpsilon;
if ( (false == temp_flag_test_optimal2) || (false == temp_flag_test_Serge_Novikoff) ) {
flag_test_optimal2 &= temp_flag_test_optimal2 ;
flag_test_Serge_Novikoff &= temp_flag_test_Serge_Novikoff ;
Console.WriteLine("");
Console.WriteLine("marketBuyPrice = " + marketBuyPrice + ", overwriteMinStep = " + overwriteMinStep);
Console.WriteLine("ret_original = " + ret);
Console.WriteLine("ret_opt2 = " + ret_opt2);
Console.WriteLine("ret_opt_Serge_Novikoff = " + ret_opt_Serge_Novikoff);
}
}
Console.WriteLine("");
Console.WriteLine("flag_test_optimal2 = " + flag_test_optimal2);
Console.WriteLine("flag_test_Serge_Novikoff = " + flag_test_Serge_Novikoff);
//*/
}
public static decimal test_original(decimal marketBuyPrice, decimal overwriteMinStep)
{
decimal mediumPrice2 = 0;
do
{
mediumPrice2 += overwriteMinStep;
} while (mediumPrice2 < marketBuyPrice);
return mediumPrice2;
}
public static decimal test_optimal2(decimal marketBuyPrice, decimal overwriteMinStep)
{
//if (decimal.Zero == marketBuyPrice) // == 0 // косячок
if (Math.Abs(marketBuyPrice) < DecimalEpsilon) // == 0
return overwriteMinStep;
decimal mediumPrice2 = (decimal.Floor(marketBuyPrice / overwriteMinStep) + 1) * overwriteMinStep;
//if ( mediumPrice2 == marketBuyPrice + overwriteMinStep )
//if ( Math.Abs(mediumPrice2 - (marketBuyPrice + overwriteMinStep)) <= 0.0001m )
if ( Math.Abs(mediumPrice2 - (marketBuyPrice + overwriteMinStep)) < DecimalEpsilon )
mediumPrice2 -= overwriteMinStep;
return mediumPrice2;
}
public static decimal test_optimal_Serge_Novikoff(decimal marketBuyPrice, decimal minStep)
{
////if (decimal.Zero == marketBuyPrice) // == 0 // косячок
//if (Math.Abs(marketBuyPrice) < DecimalEpsilon) // == 0
// return minStep;
var imin = (int)(marketBuyPrice / minStep);
if (minStep * imin < marketBuyPrice)
++imin;
decimal mediumPrice2 = minStep * imin;
return mediumPrice2;
}
}
|
| |
проверял для overwriteMinStep > 0 и marketBuyPrice >= 0,
P.S.:
если опять возникнут какие либо проблемы, то регулируйте степень (Pow) десятки в DecimalEpsilon — с 6 до нужного большего числа .. (чтобы увеличить делитель единицы), работоспособный минимум на данных тестах 1/(10^24)