deadManN deadManN - 1 month ago 15
C# Question

Substring a Number Using Math or String Conversion and .Substring()

I'm about to go through these calculation, so i thought hey why i just don't use substring, and then again i thought if it gonna be slow...

i remember a teacher from college teaching some old delphy based graphical engine, told us to try your calculation using plus instead of multiply, as it's really slow compare to multiply implementation. so the nature of math should be fast, but using so many multiplication and division...

so i though i come here and ask you that...

Some guy use integer for datetime in his web service, and i want to part it to a model...
As i said i wanted to write .toString but then i though it may be slow, so i though i gonna search first, after seeing nothing i thought of asking you, but then i realize that i have to write it before i can ask the question...

so here's sample code:

StartDate = Pc.ToDateTime(
value/10000,
(value - (value/10000)*10000)/100,
value - ((value/10000)*10000) - (((value - (value/10000)*10000)/100)*100),
0,
0,
0,
0
);


verses

Pc.ToDateTime(
Convert.ToInt32(value.ToString().SubString(0,4)),
Convert.ToInt32(value.ToString().SubString(4,2)),
Convert.ToInt32(value.ToString().SubString(6,2)),
0,
0,
0,
0
);


EDIT
Pc => private static readonly PersianCalendar Pc = new PersianCalendar();

EDIT 2

AS @Yeldar Kurmangaliyev Said, i changed my first code to:

StartDate = Pc.ToDateTime(
value/10000,
value%10000/100,
value%100,
0,
0,
0,
0
);


EDIT 3



As you suggested i used a way to measure performance my self.
here i used stopwatch:

&Edit 4 : I added Ivan Stoev sample code:

public ActionResult PerformanceMeasure()
{
PersianCalendar pc = new PersianCalendar();
var first = 0L;
var second = 0L;
var third = 0L;
var forth = 0L;

var value = 13950812;
Stopwatch sw = new Stopwatch();

sw.Reset();
sw.Start();
pc.ToDateTime(
value / 10000,
(value - (value / 10000) * 10000) / 100,
value - ((value / 10000) * 10000) - (((value - (value / 10000) * 10000) / 100) * 100),
0,
0,
0,
0
);
sw.Stop();
first = sw.ElapsedTicks;
sw.Reset();


sw.Reset();
sw.Start();
pc.ToDateTime(
value / 10000,
value % 10000 / 100,
value % 100,
0,
0,
0,
0
);
sw.Stop();
second = sw.ElapsedTicks;
sw.Reset();


sw.Reset();
sw.Start();
pc.ToDateTime(
Convert.ToInt32(value.ToString().Substring(0, 4)),
Convert.ToInt32(value.ToString().Substring(4, 2)),
Convert.ToInt32(value.ToString().Substring(6, 2)),
0,
0,
0,
0
);
sw.Stop();
third = sw.ElapsedTicks;
sw.Reset();


sw.Reset();
sw.Start();
int month, day;
int year = Math.DivRem(Math.DivRem(value, 100, out day), 100, out month);
pc.ToDateTime(
year,
month,
day,
0,
0,
0,
0);
sw.Stop();
forth = sw.ElapsedTicks;
sw.Reset();

var ms = new { First = first, Second = second, Third = third, Forth = forth };

return Json(ms, JsonRequestBehavior.AllowGet);
}


And Here are the Results, in multiple run

RUN 1:{"First":70,"Second":41,"Third":52,"Forth":42}
RUN 2:{"First":64,"Second":37,"Third":44,"Forth":37}
RUN 3:{"First":81,"Second":45,"Third":70,"Forth":47}
RUN 4:{"First":63,"Second":37,"Third":44,"Forth":38}
RUN 5:{"First":68,"Second":37,"Third":45,"Forth":37}
RUN 6:{"First":65,"Second":37,"Third":46,"Forth":38}
RUN 7:{"First":76,"Second":41,"Third":51,"Forth":41}
RUN 8:{"First":62,"Second":37,"Third":47,"Forth":37}
RUN 9:{"First":57,"Second":37,"Third":45,"Forth":37}
RUN 0:{"First":62,"Second":37,"Third":45,"Forth":38}

Answer

When used properly, math is always better than going thru double conversion from value to string and string to other value.

Just don't duplicate the calculations. Use local variables for storing the intermediate results. Especially with such calculations that involve division and modulus.

In the concrete case, IMO the optimal solution is as follows:

static DateTime ToDateTime(int value)
{
    int month, day;
    int year = Math.DivRem(Math.DivRem(value, 100, out day), 100, out month);
    return Pc.ToDateTime(year, month, day, 0, 0, 0, 0);
}