【发布时间】:2014-09-14 21:01:25
【问题描述】:
我一直听说 C++ 比 Java 更高效(这就是为什么大多数游戏都是用 C++ 开发的)。
我写了一个小算法来解决 Java 和 C++ 中的“八皇后谜题”,使用完全相同的算法,然后开始提高数字或平方。 当达到 20*20 甚至 22*22 的棋盘格时,Java 似乎更有效(3 秒对 C++ 的 66 秒)。
我不知道为什么,但我刚开始使用 C++,所以我可能犯了一些严重的性能错误,所以我很乐意接受任何有助于我理解正在发生的事情的信息。
以下是我在 Java 中使用的代码:
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
public class HuitDames {
/**
* La liste des coordnnées des dames.
*/
private static List<Point> positions = new ArrayList<>();
/**
* Largeur de la grille.
*/
private static final int LARGEUR_GRILLE = 22;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
int i = 1;
placerDame(i);
for (Point point : positions) {
System.out.println("(" + point.x + "; " + point.y + ")");
}
}
/**
* Place une dame et return true si la position est bonne.
* @param i le numéro de la dame.
* @return si la position est bonne.
*/
private static boolean placerDame(int i) {
boolean bonnePosition = false;
for (int j = 1; j <= LARGEUR_GRILLE && bonnePosition == false; j++) {
Point emplacement = new Point(i, j);
positions.add(emplacement);
if (verifierPrise(emplacement) && (i == LARGEUR_GRILLE || placerDame(i + 1))) {
bonnePosition = true;
}
else {
positions.remove(i - 1);
}
}
return bonnePosition;
}
/**
* Vérifie que la nouvelle position n'est pas en prise avec une position déjà présente.
* @param position la position de la nouvelle dame.
* @return Si la position convient par rapport aux positions des autres dames.
*/
private static boolean verifierPrise(Point position) {
boolean nonPrise = true;
for (Point point : positions) {
if (!point.equals(position)) {
// Cas où sur la même colonne.
if (position.y == point.y) {
nonPrise = false;
}
// Cas où sur même diagonale.
if (Math.abs(position.y - point.y) == Math.abs(position.x - point.x)) {
nonPrise = false;
}
}
}
return nonPrise;
}
}
下面是C++代码:
#include <iostream>
#include <list>
#include <math.h>
#include <stdlib.h>
using namespace std;
// Class to represent points.
class Point {
private:
double xval, yval;
public:
// Constructor uses default arguments to allow calling with zero, one,
// or two values.
Point(double x = 0.0, double y = 0.0) {
xval = x;
yval = y;
}
// Extractors.
double x() { return xval; }
double y() { return yval; }
};
#define LARGEUR_GRILLE 22
list<Point> positions;
bool verifierNonPrise(Point emplacement) {
bool nonPrise = true;
for (list<Point>::iterator it = positions.begin(); it!= positions.end(); it++) {
if (it->x() != emplacement.x()) {
if (it->y() == emplacement.y()) {
nonPrise = false;
}
if (abs(it->y() - emplacement.y()) == abs(it->x() - emplacement.x())) {
nonPrise = false;
}
}
}
return nonPrise;
}
bool placerDame(int i) {
bool bonnePosition = false;
for (int j = 1; j <= LARGEUR_GRILLE && !bonnePosition; j++) {
Point emplacement(i,j);
positions.push_back(emplacement);
if (verifierNonPrise(emplacement) && (i == LARGEUR_GRILLE || placerDame(i + 1))) {
bonnePosition = true;
}
else {
positions.pop_back();
}
}
return bonnePosition;
}
int main()
{
int i = 1;
placerDame(i);
for (list<Point>::iterator it = positions.begin(); it!= positions.end(); it++) {
cout << "(" << it->x() << "; " << it->y() << ")" << endl;
}
return 0;
}
【问题讨论】:
-
您是否在启用优化的情况下编译了您的 C++ 代码?对于 gcc 和 clang,在命令行中添加
-O3。 -
“我一直听说 C++ 比 Java 更高效”——因为通常是这样。
-
Java 击败 C++ 一点也不稀奇。与使用任何现成的 C++ 编译器/链接器相比,JITC 优化的 Java 程序可以得到更紧密的优化。例如,JITC 可以轻松地对 Point 进行内联操作,而 C++ 通常只有在函数声明为可内联时才能这样做。
-
@HotLicks 请注意,声明函数可内联实际上与它们是否内联无关。在这个例子中,
Point的方法是隐式内联的。但它们甚至不是必需的。数据应该是公开的。 -
@HotLicks 当然,但是 OP 的代码,一切都是内联的。性能损失很可能是使用
std::list。至于 getter,如果内联,这些也会被优化,但使用它们可能会导致数据成员的额外副本被制作,因为从语义上它们返回值。无论如何,如果在这两种语言中正确编码,很难看出 Java 如何在如此简单的数字问题上胜过 C++。我也不认为 C++ 的性能会大大超过 Java。
标签: java c++ performance algorithm