【问题标题】:Substring a Number Using Math or String Conversion and .Substring()使用数学或字符串转换和 .Substring() 对数字进行子串化
【发布时间】:2017-03-15 11:56:59
【问题描述】:

我即将完成这些计算,所以我想为什么我不使用子字符串,然后我又想它会不会很慢......

我记得一位大学老师教过一些旧的基于 delphy 的图形引擎,告诉我们尝试使用 plus 而不是乘法计算,因为与乘法实现相比它真的很慢。所以数学的本质应该是很快的,但是使用了这么多的乘法和除法......

所以我虽然来这里问你...

有些人在他的网络服务中使用整数作为日期时间,我想把它分成一个模型...... 正如我所说我想写 .toString 但后来我虽然它可能很慢,所以我虽然我会先搜索,在没有看到我想问你之后,但后来我意识到我必须先写它才能问问题...

下面是示例代码:

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

诗句

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
);

编辑 Pc => 私有静态只读 PersianCalendar Pc = new PersianCalendar();

编辑 2

正如@Yeldar Kurmangaliyev 所说,我将我的第一个代码更改为:

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

编辑 3

正如你所建议的,我使用了一种方法来衡量我自己的表现。 这里我使用秒表:

&Edit 4:我添加了 Ivan Stoev 示例代码:

    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);
    }

这是多次运行的结果

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}

让我补充一下,当我更紧密更快地运行它时,就像在我开始将每次运行复制粘贴到这里之前一样,第四次更快第二次,但并非一直如此,似乎一旦进行了计算,将被缓存一小段时间。顺便说一句,差异仍然没有那么大。

【问题讨论】:

标签: c# performance numbers substring


【解决方案1】:

忘记速度吧,从可理解性/维护的角度来看,您的任何一种方式都不是有效的。

你应该做的只是:

var myDate = DateTime.ParseExact(value.ToString(), "yyyyMMdd", CultureInfo.InvariantCulture);

不要试图过早地优化您的程序。这不太可能很快成为瓶颈。

【讨论】:

  • 我不使用公历这就是为什么我将它们传递给 PersianCalendar,似乎我想念那个
  • @deadManN 我通过CultureInfo.InvariantCulture 的第三个参数也可能是适当的文化信息 - 即new CultureInfo(“fa-Ir”) - 你可能想看看它是否有你期望的行为(恐怕我不知道波斯历的行为与公历有何不同)
  • 是的,我不知道为什么,但微软在那种文化中使用公历,这是很长时间的错误,一直存在,而且有很多代码行你必须有权让它几乎正确
【解决方案2】:

如果使用得当,数学总是比从值到字符串和字符串到其他值的双重转换要好。

只是不要重复计算。使用局部变量来存储中间结果。尤其是涉及除法和模数的计算。

具体情况下,IMO最优解如下:

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);
}

【讨论】:

  • 你是正确的,正如性能测量所说的那样,但你在一个地方错了,但为了确保我也尝试过你的,..它有时更快有时更慢......我的经验在某些游戏引擎中,我在每一帧上填充了一个变量字段,当用户与该对象发生碰撞时,我的帧速率下降到半秒或更糟,所以在某些时候我添加了一个多条件 if 并且它上升到400FPS,所以我知道如果我们从内存中读取值比写入它花费的时间要少得多,我知道即使是逻辑的东西也需要写东西,但它会更本地化,所以
  • 在本地注册表和CPU缓存中没有关系,我不确定我说的是否正确,如果计算机真的那样工作,也许我字段本身就有与其他人的联系是,但它是如此巨大的差异,我无法忘记,我是这样想的。我能想到的唯一解释
  • 我猜这是 JIT 优化的问题。由于 Intel CPU 除法指令返回结果和余数,通过适当的优化,2 个 DivRem 调用将只是 2 个 CPU 指令:)
  • 虽然我的可以更多,但是当我们不检查项目设置的优化时,因为它需要它进行调试。
猜你喜欢
  • 1970-01-01
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-01
  • 2017-01-17
相关资源
最近更新 更多