我可以加快我的特殊回合功能吗

本文关键字:功能 我的 我可以 | 更新日期: 2023-09-27 18:20:41

我有这个函数:

int round(double val) {
    if (val >= 0) {
        return (int)Math.Floor(val + 0.5);
    }
    return (int)Math.Ceiling(val - 0.5);
}

我在我的程序中多次调用它,我的意思是很多次,所以它的每一毫秒运行时间都很重要。有没有什么办法比现在更快?Thx

编辑:

该函数是计算图像中直线切线方向的算法的一部分。它取自学术文章。当它以弧度值处理角度时,它使用小而精确的数字。

I/O示例:

0 -> 0
1 -> 1
1.1 -> 1
1.51 -> 2
-0.1 -> 0
-1 -> -1
-1.1 -> -1
-1.51 -> -2

第2版:

根据评论,我将检查的功能更改为以下功能:

int round(double val) {
    return (int)Math.Round(val, MidpointRounding.AwayFromZero);
}

更新后的问题是:Math.Round函数是最快的舍入方法吗?

我可以加快我的特殊回合功能吗

您可以加快速度。这要快很多倍:

        if (val >= 0)
        {
            return (int)(val + 0.5d);
        }
        return = (int)(val - 0.5d);

你可以避开那些数学库里的东西。问题是,这真的重要吗?对于1500000次转换,You first函数的时间为18ms。您的EDIT2功能为36ms。此功能为4ms。

根据这一测量,处理器可以在大约2.5纳秒内比较两个双打,添加两个双打并转换一个双打。但如果它的缓存中没有,从主内存读取可能需要100ns。衡量有时会产生误导。

这是完整的代码

#region stopky
        public class Stopky
        {
            [System.Runtime.InteropServices.DllImport("kernel32.dll")]
            private static extern bool QueryPerformanceFrequency(out long frequency);
            [System.Runtime.InteropServices.DllImport("kernel32.dll")]
            private static extern bool QueryPerformanceCounter(out long ticks);
            protected static double frequency = -1;
            public void setStart()
            {
                QueryPerformanceCounter(out tickStart);
            }
            public double getTimeFromStart
            {
                get
                {
                    QueryPerformanceCounter(out tickNow);
                    double time = (tickNow - tickStart) / frequency;
                    return time;
                }
            }
            private long tickStart;
            private long tickNow;
            public Stopky()
            {
                if (frequency < 0)
                {
                    long tmp;
                    QueryPerformanceFrequency(out tmp);
                    if (tmp == 0)
                    {
                        throw new NotSupportedException("Error while querying "
               + "the high-resolution performance counter.");
                    }
                    frequency = tmp;
                }
                setStart();
            }
            public void Show()
            {
                MessageBox.Show(this.getTimeFromStart.ToString());
            }

        }
        #endregion


        private void button2_Click(object sender, EventArgs e)
        {
            double[] examples = new double[] { 0, 1, 1.1, 1.51, -0.1, -1, -1.1, -1.51 };
            int totalCount = 1500000;
            double[] examplesExpanded = new double[totalCount];
            for (int i = 0, j = 0; i < examplesExpanded.Length; ++i)
            {
                examplesExpanded[i] = examples[j];
                if (++j >= examples.Length) { j = 0; }
            }
            int[] result1 = new int[totalCount];
            int[] result2 = new int[totalCount];
            int[] result3 = new int[totalCount];
            Stopky st = new Stopky();
            for (int i = 0; i < examplesExpanded.Length; ++i)
            {
                result1[i] = (int)Math.Round(examplesExpanded[i], MidpointRounding.AwayFromZero);
            }
            st.Show();
            st = new Stopky();
            for (int i = 0; i < examplesExpanded.Length; ++i)
            {
                double val = examplesExpanded[i];
                if (val >= 0)
                {
                    result2[i] = (int)Math.Floor(val + 0.5);
                }
                result2[i] = (int)Math.Ceiling(val - 0.5);
            }
            st.Show();
            st = new Stopky();
            for (int i = 0; i < examplesExpanded.Length; ++i)
            {
                double val = examplesExpanded[i];
                if (val >= 0)
                {
                    result3[i] = (int)(val + 0.5d);
                }
                else
                {
                    result3[i] = (int)(val - 0.5d);
                }
            }
            st.Show();
            for (int i = 0; i < totalCount; ++i)
            {
                if(result1[i] != result2[i] || result1[i] != result3[i])
                {
                    MessageBox.Show("ERROR");
                }
            }
            MessageBox.Show("OK");
        }

部分钞票

  • i<examplesExpanded.Length比i<totalCount,尽管这与直觉相反。原因是,可以避免范围检查
  • 发布可能比调试快得多(这里的区别不大)

为什么不使用内置的Math.Round方法?

int round(double val) {
    if (val >= 0) {
        return Math.Round(val, MidpointRounding.AwayFromZero);
    }
    return Math.Round(val, MidpointRounding.ToEven);
}

https://msdn.microsoft.com/en-us/library/system.math.round(v=vs.110).aspx