调整铸造与铸造Math.Floor

时间:2014-10-03 19:40:18

标签: java c# casting

前几天我想到了这个。如果我们要将double转换为int保留Math.Floor行为并且不担心溢出,为什么我们不正常投射它们并进行简单检查以获得与{{{{{ 1}}?

我继续用C#编写了这个方法:

Math.Floor

根据我的测试,public int TweakedCast(double num) { int ret = (int)num; if (ret > num) ret--; return ret; } 最多只有一半时间TweakedCast(num)

我有很多问题 这是一种可行的方式来(int)Math.Floor(num)double演员而不用担心溢出吗? 对于所有数字,结果是否相同(即在两种方法中),即使是intNaNPositiveInfinity? 使用NegativeInfinity会有什么缺点吗? 为什么TweakedCast最多占用一半的时间?是因为TweakedCast是为双打而设计的吗?

我还想知道在Java中使用它时这段代码是否也会这样做,因为我没有正确的设置来进行测试。

1 个答案:

答案 0 :(得分:0)

由于没有人得到答案,我测试了一下并得到了这些结果。

我制作了这个基准测试程序,看看结果是否总是一样的:

class Program
{
    // all the code is unchecked, overflow is not important.
    static void Main(string[] args)
    {
        Stopwatch sw = new Stopwatch();
        Random rand = new Random();

        // Check random numbers (positive and negative) and see if they are the same on both function.
        for (int i = 0; i < 5; i++)
        {
            double num = (rand.NextDouble() + rand.Next(10000)) * (rand.NextDouble() >= 0.5 ? 1 : -1);
            Console.WriteLine("TweakedCast({0}) = {1}", num, TweakedCast(num));
            Console.WriteLine("Math.Floor({0}) = {1}", num, Floor(num));
            Console.WriteLine();
        }

        Console.WriteLine("TweakedCast({0}) = {1}", double.PositiveInfinity, TweakedCast(double.PositiveInfinity));
        Console.WriteLine("Math.Floor({0}) = {1}", double.PositiveInfinity, Floor(double.PositiveInfinity));
        Console.WriteLine();
        Console.WriteLine("TweakedCast({0}) = {1}", double.NegativeInfinity, TweakedCast(double.NegativeInfinity));
        Console.WriteLine("Math.Floor({0}) = {1}", double.NegativeInfinity, Floor(double.NegativeInfinity));
        Console.WriteLine();
        Console.WriteLine("TweakedCast({0}) = {1}", double.NaN, TweakedCast(double.NaN));
        Console.WriteLine("Math.Floor({0}) = {1}", double.NaN, Floor(double.NaN));
        Console.WriteLine();

        double a = rand.NextDouble() + rand.Next(10000);
        double b = -(rand.NextDouble() + rand.Next(10000));

        Console.WriteLine("a: {0}, b: {1}", a, b);
        Console.WriteLine("After 25 million iteration of both a and b on both methods, the result is:");
        sw.Start();
        for (int i = 0; i < 50000000; i++)
        {
            TweakedCast(a);
            TweakedCast(b);
        }
        sw.Stop();
        Console.WriteLine("TweakedCast time: {0}", sw.ElapsedMilliseconds);

        sw.Restart();
        for (int i = 0; i < 50000000; i++)
        {
            Floor(a);
            Floor(b);
        }
        sw.Stop();
        Console.WriteLine("Math.Floor time: {0}", sw.ElapsedMilliseconds);

        Console.ReadKey();
    }

    static int TweakedCast(double num)
    {
        int ret = (int)num;
        if (ret > num)
            ret--;
        return ret;
    }

    static int Floor(double num)
    {
        return (int)Math.Floor(num);
    }
}

<强>结果:

TweakedCast(-7668.35019480127) = -7669
Math.Floor(-7668.35019480127) = -7669

TweakedCast(-3737.06628523304) = -3738
Math.Floor(-3737.06628523304) = -3738

TweakedCast(-8627.20293022795) = -8628
Math.Floor(-8627.20293022795) = -8628

TweakedCast(9332.33679385313) = 9332
Math.Floor(9332.33679385313) = 9332

TweakedCast(-6910.65257059767) = -6911
Math.Floor(-6910.65257059767) = -6911

TweakedCast(Infinity) = -2147483648
Math.Floor(Infinity) = -2147483648

TweakedCast(-Infinity) = 2147483647
Math.Floor(-Infinity) = -2147483648

TweakedCast(NaN) = -2147483648
Math.Floor(NaN) = -2147483648

a: 9772.35618077747, b: -945.045879946577
After 25 million iteration of both a and b on both methods, the result is:
TweakedCast time: 2326
Math.Floor time: 4317

回答我的问题:
1- TweakedCast是一种可行的方法,只要double位于int.MinValueint.MaxValue的边界内,就可以将整数作为整数。

2-对于几乎所有值,Math.FloorTweakedCast的结果都相同。唯一的例外是double.NegativeInfinity,它会在int.MaxValue中以TweakedCastint.MinValue中的Math.Floor返回,这很可能是因为{Math.Floor所做的检查1}}。

3-我发现的唯一不足之处在于,它仅适用于int.MinValueint.MaxValue之间以及前一个回答中提及double.NegativeInfinity的事实。

4-我对此没有明确的答案,但我的猜测是使用的算法不同,Math.Floor开头的检查也可能产生很小的影响。此外,double的大小是int的两倍,但这也最不可能生效。

注意:我搜索了一个用Java制作的流行视频游戏的代码,他们有一个实用程序类可以实现更快的数学运算,并且使用铸造的地板方法完全相同简单的检查。这证明TweakedCast可以完美地用于java。