Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';在C#中获取数字的部分值的最快方法是什么?_C#_Floating Point - Fatal编程技术网

什么';在C#中获取数字的部分值的最快方法是什么?

什么';在C#中获取数字的部分值的最快方法是什么?,c#,floating-point,C#,Floating Point,没有比每次调用外部函数更快的方法了吗?“外部函数” 系统。数学内置于mscorlib中 这实际上是最快的方法。它是静态的,所以速度应该非常快,没有物体可以站立。你总是可以进行位级的数学运算,但除非你认真使用这个函数。很可能floor()方法已经在这样做了,但是如果你需要一些非常快速的东西,你可以内联它并删除检查等,但是在C中,这不是你最大的性能问题。好吧,我怀疑你会得到任何实际的性能增益,但是根据Reflector Math。floor是这样的: float f = 5.13; double d

没有比每次调用外部函数更快的方法了吗?

“外部函数”

系统。数学内置于mscorlib中


这实际上是最快的方法。

它是静态的,所以速度应该非常快,没有物体可以站立。你总是可以进行位级的数学运算,但除非你认真使用这个函数。很可能floor()方法已经在这样做了,但是如果你需要一些非常快速的东西,你可以内联它并删除检查等,但是在C中,这不是你最大的性能问题。

好吧,我怀疑你会得到任何实际的性能增益,但是根据Reflector Math。floor是这样的:

float f = 5.13;
double d = 5.13;

float fp = f - (float)Math.floor(f);
double dp = d - Math.floor(d);
可以这么说

public static decimal Floor(decimal d)
{
    return decimal.Floor(d);
}
可能更快。(编译器优化使整个观点毫无意义,我知道…)


对于那些可能有兴趣将此作为其逻辑结论的人,请发言:

double dp = d - decimal.Floor(d);

由于FCallFloor是对非托管代码的调用,因此您几乎处于“优化”的极限。

您可以将f强制转换为int,以修剪小数部分。这假设你的双打在整数范围内

当然,抖动可能足够聪明,可以将Math.floor优化为一些内联asm,这些asm将执行floor,这可能比转换为int然后再转换回float要快

您是否实际测量并验证了Math.floor的性能是否影响了您的程序?如果没有,在知道这是一个问题之前,您不应该为这一级别的微优化而烦恼,然后根据原始代码衡量此替代方案的性能

编辑:这确实显示得更快。下面的代码在使用Math.Floor()时需要717ms,在我的机器上,在释放模式下,int casting代码需要172ms。但是,我再一次怀疑性能的提高是否真的重要——为了使其可测量,我必须进行100万次迭代。此外,我发现Math.Floor()更具可读性,其意图也更为明显,未来的CLR可以为Math.Floor生成更多优化的代码,并轻松击败这种方法

public static decimal Floor(decimal d)
{
    decimal result = 0M;
    FCallFloor(ref result, d);
    return result;
}
private static double floor1测试()
{
//跟踪总体结果,以免优化运营。
双倍合计=0;
对于(int i=0;i<100000000;i++)
{
浮球f=5.13f;
双d=5.13;
浮点fp=f-(浮点)数学楼层(f);
双dp=d-(浮动)数学层(d);
总数=fp+dp;
}
返回总数;
}
专用静态双地板测试()
{
//跟踪总计,以避免优化运营。
双倍合计=0;
对于(int i=0;i<100000000;i++)
{
浮球f=5.13f;
双d=5.13;
浮点fp=f-(int)(f);
双dp=d-(int)(d);
总数=fp+dp;
}
返回总数;
}
静态void Main(字符串[]参数)
{
System.Diagnostics.Stopwatch计时器=新的System.Diagnostics.Stopwatch();
//未使用的先运行,保证代码是JIT'd。
timer.Start();
地板试验();
地板试验();
timer.Stop();
timer.Reset();
timer.Start();
地板试验();
timer.Stop();
long floor1time=定时器。延时毫秒;
timer.Reset();
timer.Start();
地板试验();
timer.Stop();
long floor2time=定时器。延时毫秒;
控制台写入线(“楼层1-{0}ms”,楼层1次);
控制台写入线(“楼层2-{0}ms”,楼层2次);
}
}
唐纳德·E·克努特说:

“我们应该忘记小效率,比如说97%的时间:过早 优化是万恶之源。”


因此,除非您已经对应用程序进行了基准测试,并找到了这种操作是瓶颈的确凿证据,否则不要在这一行代码中对其进行优化。

对于
十进制
,我建议您忽略所有喊着不要更改它的人,并尝试使用
Decimal.Truncate
。无论它是否更快,它都是一个专门用于您尝试执行的功能,因此更加清晰

哦,顺便说一下,速度更快:

    private static double Floor1Test()
    {
        // Keep track of results in total so ops aren't optimized away.
        double total = 0;
        for (int i = 0; i < 100000000; i++)
        {
            float f = 5.13f;
            double d = 5.13;
            float fp = f - (float)Math.Floor(f);
            double dp = d - (float)Math.Floor(d);
            total = fp + dp;
        }

        return total;
    }

    private static double Floor2Test()
    {
        // Keep track of total so ops aren't optimized away.
        double total = 0;
        for (int i = 0; i < 100000000; i++)
        {
            float f = 5.13f;
            double d = 5.13;
            float fp = f - (int)(f);
            double dp = d - (int)(d);
            total = fp + dp;
        }

        return total;
    }

    static void Main(string[] args)
    {
        System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();

        // Unused run first, guarantee code is JIT'd.
        timer.Start();
        Floor1Test();
        Floor2Test();
        timer.Stop();

        timer.Reset();
        timer.Start();
        Floor1Test();
        timer.Stop();
        long floor1time = timer.ElapsedMilliseconds;

        timer.Reset();
        timer.Start();
        Floor2Test();
        timer.Stop();

        long floor2time = timer.ElapsedMilliseconds;

        Console.WriteLine("Floor 1 - {0} ms", floor1time);
        Console.WriteLine("Floor 2 - {0} ms", floor2time);
    }
}
System.Diagnostics.Stopwatch foo=new System.Diagnostics.Stopwatch();
十进制x=1.5M;
十进制y=1;
int测试=1000000;
foo.Start();
对于(int z=0;z

编辑:修复了我的解释和代码。

你是说性能更快?为了打破你目前的一套坏习惯,你应该开始不断思考优化有多糟糕。你现在输入的每一个字符,你都应该考虑“它的可读性如何”。你真的不知道数学是否正确。例程甚至被内联调用或编译——如果你提出了一个代数内联解决方案,它很有可能会变慢。请不要再考虑性能了。我一直在等待有人指出他的代码至少在某些时候给出了错误的答案(比如在他的示例中,f=5.13f)。浮点fp=f-(浮点)数学。楼层(f)结果为0。1300001@Martin:根据labls.developerfusion.co.uk和koders.com,FCallFloor将十进制转换为字符串,然后截断点后面的部分。显然,如果您编写自己的非托管调用,将十进制转换为字符串,然后截断点之前的部分,则可以得到更好的结果。这避免了su
        System.Diagnostics.Stopwatch foo = new System.Diagnostics.Stopwatch();

        Decimal x = 1.5M;
        Decimal y = 1;
        int tests = 1000000;
        foo.Start();
        for (int z = 0; z < tests; ++z)
        {
            y = x - Decimal.Truncate(x);
        }
        foo.Stop();
        Console.WriteLine(foo.ElapsedMilliseconds);

        foo.Reset();
        foo.Start();
        for (int z = 0; z < tests; ++z)
        {
            y = x - Math.Floor(x);
        }
        foo.Stop();
        Console.WriteLine(foo.ElapsedMilliseconds);
        Console.ReadKey();

//Output: 123
//Output: 164