当前位置: 首页 > 知识库问答 >
问题:

为什么这段代码在java中比在C++和C#中更快

蔚俊人
2023-03-14
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <Windows.h>

long perfFrequency = 0;

typedef struct
{
    double X;
    double Y;
} Point;

double distance(Point p1, Point p2)
{
    return sqrt(pow(p1.X - p2.X, 2) + pow(p1.Y - p2.Y, 2));
}

double smallerDistance(Point *points, int size, Point *smallerA, Point  *smallerB)
{
    int i, j;
    double smaller = distance(points[0], points[1]);

    for (i = 0; i < size; i++)
    {
        for (j = i + 1; j < size; j++)
        {
            double dist = distance(points[i], points[j]);
            if (dist < smaller)
            {
                smaller= dist;
                *smallerA = points[i];
                *smallerB = points[j];
            }
        }
    }
    return smaller;
}

void main()
{
    // read size and points from file.
    int size;
    Point *points= (Point *)malloc(size * sizeof(Point));

    // just to make sure everything is ready before the benchmark begins    
    system("pause");

    Point smallerA, smallerB;
    if (!QueryPerformanceFrequency((LARGE_INTEGER *)&perfFrequency))
        printf("Couldn't query performance frequency.");

    long long start, end;   
    double smaller;
    QueryPerformanceCounter((LARGE_INTEGER *)&start);

    smaller= smallerDistance(points, size, &smallerA, &smallerB);

    QueryPerformanceCounter((LARGE_INTEGER *)&end);

    printf("The smaller distance is: %lf. The coordinates of the most close points are: (%lf, %lf) and (%lf, %lf). Time taken: %lfms\n",
        smaller, smallerA.X, smallerA.Y, smallerB.X, smallerB.Y, (end - start) * 1000.0 / perfFrequency);

}
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace StructuredTest
{
    struct Point
    {
        public double X;
        public double Y;
    }

    class Program
    {
        static double Distance(Point p1, Point p2)
        {
            return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
        }

        static double SmallerDistance(Point[] points, int size, out Point smallerA, out Point smallerB)
        {
            int i, j;
            double smaller = Distance(points[0], points[1]);
            smallerA = default(Point);
            smallerB = default(Point);

            for (i = 0; i < size; i++)
            {
                for (j = i + 1; j < size; j++)
                {
                    double dist = Distance(points[i], points[j]);
                    if (dist < smaller)
                    {
                        smaller = dist;
                        smallerA = points[i];
                        smallerB = points[j];
                    }
                }
            }

            return smaller;
        }

        static void Main(string[] args)
        {
            // read size and points from file 
            int size = int.Parse(file[0]);
            Point[] points= new Point[size];                   

            // make sure everything is ready
            Console.WriteLine("Press any key to continue...");
            Console.ReadKey(true);

            Point smallerA, smallerB;
            double smaller;

            Stopwatch sw = new Stopwatch();
            sw.Restart();

            smaller = SmallerDistance(points, size, out smallerA, out smallerB);

            sw.Stop();

            Console.WriteLine($"The smaller distance is: {smaller}. The coordinates of the most close points are: ({smallerA.X}, {smallerA.Y}) and " +
                $"({smallerB.X}, {smallerB.Y}). Time taken: {sw.ElapsedMilliseconds}ms.");

        }
    }
}

Java:

package structuredtest;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

class Point {

    public Point(double X, double Y) {
        this.X = X;
        this.Y = Y;
    }

    double X;
    double Y;
}

class Result {

    double distance;
    Point p1;
    Point p2;
}

public class StructuredTest {

    static double distance(Point p1, Point p2) {
        return Math.sqrt(Math.pow(p1.X - p2.X, 2) + Math.pow(p1.Y - p2.Y, 2));
    }

    static Result smallerDistance(Point[] points, int size) {
        int i, j;
        double smaller = distance(points[0], points[1]);
        Result r = new Result();

        for (i = 0; i < size; i++) {
            for (j = i + 1; j < size; j++) {
                double dist = distance(points[i], points[j]);
                if (dist < smaller) {
                    smaller = dist;
                    r.p1 = points[i];
                    r.p2 = points[j];
                }
            }
        }

        r.distance = smaller;
        return r;
    }

    public static void main(String[] args) throws IOException {
        // read size and points from file
        int size = Integer.parseInt(file[0]);
        Point[] points = new Point[size];

        // make sure everything is ready    
        System.out.println("Press any key to continue...");
        System.in.read();

        double start = System.nanoTime(), end;

        Result r = smallerDistance(points, size);

        end = System.nanoTime();

        System.out.println("The smaller distance is: " + r.distance + ". The most close points are: ("
                + r.p1.X + "," + r.p1.Y + ") and " + r.p2.X + "," + r.p2.Y + "). Time taken: " + (end - start) / 1000000 + "ms.");

    }

}

如果java以微弱优势击败了C和C#我不会感到惊讶,但速度快了20倍?!

文件的格式如下:

3 // number of points in the file. Note that there no comments in the actual file
(3.7098722472288, 4.49056397953787) // point (X,Y)
(8.90232811621332, 9.67982769279173)
(5.68254334818822, 1.71918922506136)
(6.22585901842366, 9.51660500242835)
(Point 1)
(Point 2)
(Point 3)
(Point 1)
(Point 2)
(Point 3)

另外,我认为值得注意的是,java在NetBeans中运行时大约需要11秒(即使是在“运行”模式下,而不是在“调试”模式下)。

我也尝试编译为C++而不是C,但没有什么不同。

我对C和C#都使用VS2015。

x64
Optimization: Maximize Speed (/O2)
Intrinsic Functions: Yes (/Oi)
Favor Size or Speed: Favor fast code (/Ot)
Enable Fiber-Safe Optimizations: Yes (/GT)
Security Check: Disable Security Check (/GS-)
Floating point model: Fast (/fp:fast)
Everything else: default
x64
Release Mode
Optimize Code: Enabled
Check for arithmetic overflow: Disabled
.NET 4.5.2 

Java:

JRE/JDK 1.8
Default settings (if there are any)

好吧,我按照建议重新做了测试:

首先,我在C和C#中都使用了result类/struct。我在java中使用它而不是在C/C#中使用它的原因是因为java不能通过引用传递。其次,我现在在main()函数中重复这个测试。感谢@Tony D抓住了那个虫子!:)

然后,我尝试删除对Math.pow的调用(简单地更改(p1.x-p2.x)*(P1.x-p2.x))+(p1.y-p2.y)*(P1.y-p2.y))),然后一切都改变了。新的结果:

Java:平均220毫秒

C#:平均195ms

共有1个答案

伯建安
2023-03-14

正如这里解释和检查的那样,在纯C中没有整数次幂的过载,就像下面这样:

double pow(double base, int exponent );

它意味着当您在C中调用POW时,它的处理方式类似于:

double pow(double base, double exponent) {
    return exp(log(base) * exponent);
}

另外,对于负基数和整数次幂的情况也应该进行一些检查,这是以特殊的方式处理的。在这里添加if(exponent==1.0)if(exponent==2.0)这样的条件不是一个好主意,因为这会减慢真正使用pow进行适当用途的数学代码。结果,平方在十二次或类似的时间内变得更慢。

 类似资料:
  • 问题内容: 下面是分别用和编码的简单过程(对于那些对此过程感到好奇的人,这是针对Euler项目5号问题的解决方案)。 我的问题是,下面的代码仅需9秒即可迭代,而代码完成则需要283秒(确切地说,在Python 3.4.3-64位上为283秒,在Python 2.7.9-32位上为329秒)。 到目前为止,我已经编码的两种类似的过程和与执行时间的差异,具有可比性。但是,这次,经过的时间之间存在极大的

  • 问题内容: 我们注意到,用C#(或Java)开发的软件中的许多错误都导致NullReferenceException。 为什么在语言中甚至包含了“ null”? 毕竟,如果没有“ null”,那么我就不会有错误,对吧? 换句话说,如果没有null,该语言的什么功能将无法正常工作? 问题答案: “ C#父亲” Anders Hejlsberg在他的《计算机世界》采访中谈到了这一点: 例如,在类型系统

  • 我从同事那里听说C比Java快,在寻找最佳性能时,尤其是对于金融应用程序,这是要走的路。但我的观察有点不同。有人能指出我实验的失败之处,或者在讨论中添加一些科学变量吗? 注意 1:我正在使用 -O3(最大优化)和 -O2 与 C 编译器。 注2:每种语言的简短完整的源代码都包括在内。随意在自己的机器上运行,做出改变,得出结论,分享。 注3:如果您将两个源代码并排放在编辑器中,您将看到它们的实现是等

  • 我最近用Java写了一个计算密集型算法,然后把它翻译成C++。令我吃惊的是,C++的执行速度要慢得多。我现在已经编写了一个更短的Java测试程序,以及一个相应的C++程序-参见下面。我的原始代码具有大量的数组访问功能,测试代码也是如此。C++的执行时间要长5.5倍(请参阅每个程序末尾的注释)。 以下1st21条评论后的结论... null null Java代码: C++代码:

  • 我尝试使用C类继承来解决违反Liskov替换原则的问题,但无法复制与Java程序演示的LSP冲突相同的问题。Java程序的源代码可以在这个页面上找到。违规会导致页面上描述的错误。下面是我用C语言翻译的代码: 答案是矩形类预期的50。我对Java的翻译是错误的还是这与Java和C实现类的区别有关?我的问题是: 是什么导致了这种行为差异(在引擎盖下/我的代码问题)? LSP违规的Java示例可以在C中

  • 对于我的Java类,我需要在给定以下函数头的情况下创建一个函数体: