сравнение языков программирования
Модератор: Olej
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
сравнение языков программирования
Это может быть интересно и для начинающих программистов (выпускников ВУЗов) для того, чтобы определиться что из себя представляет какой язык, и куда направить сои усилия... Хотя бы для того, чтобы различать во множестве предложений вакансий "who is who" и как расшифровать требования работодателя.
Задача: написать одну и ту же задачу, максимально близко друг к другу, на различных языках программирования.
Задача не так простая, потому что хотелось бы:
- чтобы задача не была тривиальной "Hello World"
- чтобы задача не была необозримого объёма, преимущество минимальной формулировке
- чтобы код реализации задачи на каждом из языков включал в себя самые специфические возможности этого языка.
... пока всё
В общем, тема эта для тех начинающих, кто хотел бы различать и определиться на каком из языков программирования ... его будущее
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: сравнение языков программирования
Есть у меня на примете такая задача: просчёт треугольника - вы вводите координаты 3-х вершин треугольника, и получаете в ответ его периметр и площадь:Olej писал(а):Задача не так простая, потому что хотелось бы:
Код: Выделить всё
olej@notebook:~/2014_WORK/ManyLan$ ./triangle
координаты вершин в формате: X Y
вершина № 1: 0 0
вершина № 2: 1 0
вершина № 3: 0 1
треугольник: [0.00,0.00] [1.00,0.00] [0.00,1.00]
периметр = 3.41
площадь = 0.50
---------------------------------
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: сравнение языков программирования
Т.е. вопросы довольно широкие, но не противопоставление ... вот такого сорта:Olej писал(а):Мне для одного из моих коллег понадобилось сделать такое сравнение ... но не в смысле C vs Java, а показать сравнение кодов на различных языках для решения одной и той же задачи.
- как выглядит код на разных языках
- какие особенности использования такого кода: компиляция, интерпретация, компиляция в байт код...
- какие инструменты используются для подготовки и использования (компиляторы, интерпретаторы): gcc, clang, python, python3, javac, java, smjs, php5, lua и др.
- где брать такие инструменты, если их нет в системе, и как устанавливать
- как использовать полученное приложение, как выполнять
- какая степень переносимости между ОС и аппаратными платформами
Вместо того, чтобы объяснять это всё "на пальцах", как делают (и то иногда) студентам в ВУЗе ... когда говорится: вот вам PASCAL, и лабай на нём - это круто.
Но лучше 1 раз показать, чем 10 раз рассказывать: вот иметь такие коды приложений - и бери, собирай используй и смотри ... через руки.
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: сравнение языков программирования
Вот 1-й эталонный вариант, от которого буду отталкиваться - на C (и мне на C проще всего писать + и для Linux язык C самый естественный и органичный):Olej писал(а):Есть у меня на примете такая задача: просчёт треугольника - вы вводите координаты 3-х вершин треугольника, и получаете в ответ его периметр и площадь:Olej писал(а):Задача не так простая, потому что хотелось бы:
Код: Выделить всё
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
#define NODES 3
typedef double complex triangle_t [ NODES ]; // тип треугольника
static double perimeter( triangle_t pts ) {
double summa = 0.0;
int i, j;
for( i = 0; i < NODES; i++ ) {
j = NODES - 1 == i ? 0 : i + 1;
summa += cabs( pts[ i ] - pts[ j ] );
}
return summa;
}
static double square( triangle_t pts ) {
double complex side1 = pts[ 1 ] - pts[ 0 ],
side2 = pts[ 2 ] - pts[ 0 ];
return cabs( side1 ) * cabs( side2 ) *
fabs( sin( carg( side1 ) - carg( side2 ) ) ) / 2.;
}
int main( int argc, char **argv, char **envp ) {
while( 1 ) {
int m, i = 0;
triangle_t points;
printf( "координаты вершин в формате: X Y\n" );
while( i < NODES ) {
float x = -1., y = -1.;
printf( "вершина № %d: ", i + 1 );
fflush( stdout );
if( EOF == ( m = scanf( "%f%*c%f", &x, &y ) ) )
printf( "завершение\n" ), exit( EXIT_SUCCESS );
points[ i ] = x + I * y;
if( m != 2 ) {
printf( "ошибка ввода!\n" );
scanf( "%*s" );
continue;
}
i++;
}
printf( "треугольник:" );
for( i = 0; i < NODES; i++ )
printf( " [%.2f,%.2f]",
creal( points[ i ] ), cimag( points[ i ] ) );
printf( "\nпериметр = %.2f\nплощадь = %.2f\n"
"---------------------------------\n",
perimeter( points ), square( points ) );
}
}
Код: Выделить всё
olej@notebook:~/2014_WORK/ManyLan$ gcc -Wall -lm triangle.c -o triangle_c
Код: Выделить всё
olej@notebook:~/2014_WORK/ManyLan$ clang -Wall -lm triangle.c -o triangle_c
Код: Выделить всё
olej@notebook:~/2014_WORK/ManyLan$ ./triangle_c
координаты вершин в формате: X Y
вершина № 1: -1 0
вершина № 2: 0 1
вершина № 3: 1 0
треугольник: [-1.00,0.00] [0.00,1.00] [1.00,0.00]
периметр = 4.83
площадь = 1.00
---------------------------------
координаты вершин в формате: X Y
вершина № 1: завершение
- Вложения
-
- triangle.c
- (1.62 КБ) 617 скачиваний
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: сравнение языков программирования
Там есть довольно любопытные детали ... для дальнейшего сравнения с другими реализациями:Olej писал(а): Вот 1-й эталонный вариант, от которого буду отталкиваться - на C (и мне на C проще всего писать + и для Linux язык C самый естественный и органичный):
1. Для 2D координатного представления используется тип double complex - это новинка в C, добавленная стандартом C99. Это можно использовать успешно не только для таких игрушечных задач, но и вообще для 2D проектов.
2. Определяется новый тип данных (для этой задачи):
Код: Выделить всё
typedef double complex triangle_t [ NODES ]; // тип треугольника
Но в случае языка C - это чисто формальное определение типа, ничего нового не добавляющее, кроме удобства чтения человеком.
3. На вводе данных сделана кой-какая (не тщательная, чтобы не усложнять) обработка ошибок ввода. Сделано специально, потому как именно модель ввода, а особенно обработка ошибок, будут радикально отличаться в разноязыковых реализациях.
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: сравнение языков программирования
Следующий вариант, естественно, C++.Olej писал(а):Вот 1-й эталонный вариант, от которого буду отталкиваться - на C (и мне на C проще всего писать + и для Linux язык C самый естественный и органичный):
(Почему естественно? для интересующихся... Потому что C++ - надмножество C, почти всякий код C можно скомпилировать компилятором C++ ... редкие примеры когда нельзя это сделать - специально коллекционируют. Приводимый раньше пример вполне компилируется и в режиме C++)
Код: Выделить всё
#include <stdlib.h>
#include <complex>
#include <iostream>
using namespace std;
//#define NODES 3
const int NODES = 3;
// class point : public complex<double> {
class point { // класс вершины
protected:
complex<double> xy;
public:
friend class triangle;
friend ostream& operator << ( ostream& stream, point& obj );
friend istream& operator >> ( istream& stream, point& obj );
};
inline ostream& operator << ( ostream& stream, point& obj ) {
stream << "[" << obj.xy.real() << "," << obj.xy.imag() << "]";
return stream;
};
inline istream& operator >> ( istream& stream, point& obj ) {
double x, y;
string s;
cin >> x >> y;
getline( cin, s );
obj.xy = complex<double>( x, y );
return stream;
};
class triangle { // класс треугольник
protected:
point pt[ NODES ];
public:
double perimeter( void ) {
double summa = 0.0;
int i, j;
for( i = 0; i < NODES; i++ ) {
j = NODES - 1 == i ? 0 : i + 1;
summa += abs( pt[ i ].xy - pt[ j ].xy );
}
return summa;
}
double square( void ) {
complex<double> side1 = pt[ 1 ].xy - pt[ 0 ].xy,
side2 = pt[ 2 ].xy - pt[ 0 ].xy;
return abs( side1 ) * abs( side2 ) *
fabs( sin( arg( side1 ) - arg( side2 ) ) ) / 2.;
}
inline point& operator [] ( int i ) { return pt[ i ]; }
friend istream& operator >> ( istream& stream, triangle& obj ) {
for( int i = 0; i < NODES; i++ ) {
cout << "вершина № " << i + 1 << " : " << flush;
stream >> obj.pt[ i ];
if( stream.eof() ) return stream;
}
return stream;
}
};
int main( int argc, char **argv, char **envp ) {
cout.precision( 3 );
while( 1 ) {
int i = 0;
triangle points;
cout << "координаты вершин в формате: X Y" << endl;
if( ( cin >> points ).eof() )
cout << "завершение" << endl, exit( EXIT_SUCCESS );
cout << "треугольник:";
for( i = 0; i < NODES; i++ )
cout << " " << points[ i ];
cout << endl << "периметр = " << points.perimeter() << endl
<< "площадь = " << points.square() << endl
<< "---------------------------------" << endl;
}
}
Код: Выделить всё
olej@notebook:~/2014_WORK/ManyLan$ g++ -Wall -lm triangle.cc -o triangle_cc
Код: Выделить всё
olej@notebook:~/2014_WORK/ManyLan$ ./triangle_cc
координаты вершин в формате: X Y
вершина № 1 : -1 0
вершина № 2 : 0 1
вершина № 3 : 1 0
треугольник: [-1,0] [0,1] [1,0]
периметр = 4.83
площадь = 1
---------------------------------
координаты вершин в формате: X Y
вершина № 1 : завершение
- Вложения
-
- triangle.cc
- (2.28 КБ) 602 скачивания
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: сравнение языков программирования
Здесь присутствует по максимуму (для такого короткого примера) характерных отличий C++ от C (к вопросу: в чём разница):Olej писал(а): Следующий вариант, естественно, C++.
1. Определяются классы, и позже создаются объекты этих классов:
Код: Выделить всё
class point { // класс вершины
...
class triangle { // класс треугольник
...
Это и есть объектное программирование - главное отличие C++.
Отмечаем, что объекты C++ существуют только в коде до времени компиляции. Структура откомпилированного ELF-файла, пригодного для исполнения, ничем не отличается от такого же из C. Никаких объектов времени исполнение там нет. В других языках программирования это может быть не так.
(Здесь интересно, что даже в коде C может быть воссоздана объектная модель программирования, и в таком коде могут быть построены подсистемы, в которых объекты будут присутствовать и в бинарном коде периода выполнения. Самый показательный пример здесь - это в OS QNX графическая подсистема Photon - огромная по величине подсистема, замещающая графическую подсистему X11)
2. Новые файл-хэдеры (наравне со старыми C) и используемые в них пространства имён (namespace):
Код: Выделить всё
#include <stdlib.h>
#include <complex>
#include <iostream>
using namespace std;
...
3. Необходимость в препроцессоре практически отпадает: вместо препроцессорных констант - переменные константных типов, а вместо макросов - использование гораздо более мощного механизма шаблонов (template):
Код: Выделить всё
//#define NODES 3
const int NODES = 3;
4. Вместо встроенного типа C complex используется шаблонный тип C++:
Код: Выделить всё
complex<double> xy;
Код: Выделить всё
if( ( cin >> points ).eof() )
cout << "завершение" << endl, exit( EXIT_SUCCESS );
Код: Выделить всё
friend ostream& operator << ( ostream& stream, point& obj );
friend istream& operator >> ( istream& stream, point& obj );
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: сравнение языков программирования
Другой вариант (более развитый) того же приложения:Olej писал(а):Следующий вариант, естественно, C++.Olej писал(а):Вот 1-й эталонный вариант, от которого буду отталкиваться - на C (и мне на C проще всего писать + и для Linux язык C самый естественный и органичный):
Код: Выделить всё
#include <stdlib.h>
#include <complex>
#include <iostream>
using namespace std;
const int NODES = 3;
class point : public complex<double> { // класс вершины
protected:
point( void ) {
*(complex<double>*)this = complex<double>( 0, 0 );
}
point( const complex<double>& c ) {
*(complex<double>*)this = c;
}
public:
friend class triangle;
friend ostream& operator << ( ostream& stream, point& obj );
friend istream& operator >> ( istream& stream, point& obj );
};
inline ostream& operator << ( ostream& stream, point& obj ) {
stream << "[" << obj.real() << "," << obj.imag() << "]";
return stream;
};
inline istream& operator >> ( istream& stream, point& obj ) {
double x, y;
string s;
cin >> x >> y;
getline( cin, s );
obj = point( complex<double>( x, y ) );
return stream;
};
class triangle { // класс треугольник
protected:
point pt[ NODES ];
public:
double perimeter( void ) {
double summa = 0.0;
int i, j;
for( i = 0; i < NODES; i++ ) {
j = NODES - 1 == i ? 0 : i + 1;
summa += abs( pt[ i ] - pt[ j ] );
}
return summa;
}
double square( void ) {
complex<double> side1 = pt[ 1 ] - pt[ 0 ],
side2 = pt[ 2 ] - pt[ 0 ];
return abs( side1 ) * abs( side2 ) *
fabs( sin( arg( side1 ) - arg( side2 ) ) ) / 2.;
}
inline point& operator [] ( int i ) { return pt[ i ]; }
friend istream& operator >> ( istream& stream, triangle& obj ) {
for( int i = 0; i < NODES; i++ ) {
cout << "вершина № " << i + 1 << " : " << flush;
stream >> obj.pt[ i ];
if( stream.eof() ) return stream;
}
return stream;
}
};
int main( int argc, char **argv, char **envp ) {
cout.precision( 3 );
while( 1 ) {
int i = 0;
triangle points;
cout << "координаты вершин в формате: X Y" << endl;
if( ( cin >> points ).eof() )
cout << "завершение" << endl, exit( EXIT_SUCCESS );
cout << "треугольник:";
for( i = 0; i < NODES; i++ )
cout << " " << points[ i ];
cout << endl << "периметр = " << points.perimeter() << endl
<< "площадь = " << points.square() << endl
<< "---------------------------------" << endl;
}
}
1. наследование классов;
2. разграничение прав доступа к членам класса: private, protected, public;
3. конструктор и конструктор копирования;
Код: Выделить всё
class point : public complex<double> { // класс вершины
protected:
point( void ) {
*(complex<double>*)this = complex<double>( 0, 0 );
}
point( const complex<double>& c ) {
*(complex<double>*)this = c;
}
...
- Вложения
-
- triangle.cc
- (2.36 КБ) 635 скачиваний
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: сравнение языков программирования
Лёгкое такое промежуточное замечание (наблюдение):Olej писал(а): Следующий вариант, естественно, C++.
Код: Выделить всё
olej@notebook:~/2014_WORK/ManyLan$ ls -l triangle.c*
-rw-r--r-- 1 olej olej 1656 Янв 28 22:14 triangle.c
-rw-r--r-- 1 olej olej 2412 Янв 30 13:44 triangle.cc
Поэтому когда говорится (кое-где и кое-кем), что язык C++ более высокоуровневый, чем C - это неправда. C++ предлагает просто другую модель - объектную, но уровень определяется уровнем представленных базовых структур данных, а они в C и C++ идентичны. C++ предоставляет много больше возможностей, но он не является более высокоуровневым.
И ещё замечание.
Код: Выделить всё
olej@notebook:~/2014_WORK/ManyLan$ ls -l triangle_*
-rwxr-xr-x 1 olej olej 6861 Янв 30 15:38 triangle_c
-rwxr-xr-x 1 olej olej 12589 Янв 30 15:38 triangle_cc
Приложение C собирается (по умолчанию) с библиотекой libc.so :
Код: Выделить всё
olej@notebook:~/2014_WORK/ManyLan$ ldd triangle_c
linux-gate.so.1 => (0xb76eb000)
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb76a8000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb755a000)
/lib/ld-linux.so.2 (0xb76ec000)
Код: Выделить всё
olej@notebook:~/2014_WORK/ManyLan$ ldd triangle_cc
linux-gate.so.1 => (0xb7797000)
libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xb768e000)
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb7668000)
libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xb764a000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb74fc000)
/lib/ld-linux.so.2 (0xb7798000)
В случае сборки с разделяемыми библиотеками это не так важно... Но для встраиваемых приложений, при статической сборке - это может стать существенным.
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: сравнение языков программирования
Следующий вариант, естественно , Java:Olej писал(а): Следующий вариант, естественно, C++.
(Почему естественно? для интересующихся... Потому что C++ - надмножество C, почти всякий код C можно скомпилировать компилятором C++ ... редкие примеры когда нельзя это сделать - специально коллекционируют. Приводимый раньше пример вполне компилируется и в режиме C++)
Код: Выделить всё
import java.io.*;
import java.util.StringTokenizer;
import java.lang.Double.*;
class Tric { // класс треугольник
public static final int nodes = 3;
Complex [] pt = new Complex[ nodes ];
public String toString() {
String ret = "";
for( int i = 0; i < nodes; i++ )
ret += "[" + ( new Double( pt[ i ].re ) ).toString() + "," +
( new Double( pt[ i ].im ) ).toString() + "] ";
return ret;
}
public double perimeter() {
double summa = 0.0;
for( int i = 0; i < nodes; i++ )
summa += pt[ i ].minus( pt[ nodes - 1 == i ? 0 : i + 1 ] ).r();
return summa;
}
public double square() {
Complex side1 = pt[ 1 ].minus( pt[ 0 ] ),
side2 = pt[ 2 ].minus( pt[ 0 ] );
return side1.r() * side2.r() *
Math.abs( Math.sin( side1.theta() - side2.theta() ) ) / 2.;
}
}
public class triangle {
public static void main( String[] args ) {
String szStr = "";
Console cons = System.console();
while( true ) {
Tric points = new Tric();
System.out.println( "координаты вершин в формате: X Y" );
Complex parm; // = { };
for( int i = 0; i < Tric.nodes; ) {
szStr = cons.readLine( "%s%d%s", "вершина № ", i + 1, " : " );
if( null == szStr ) { // ^D
System.out.println( "" );
System.exit( 0 );
}
StringTokenizer st = new StringTokenizer( szStr, " \r\n" );
try {
double x = ( new Double( (String)st.nextElement() ) ).doubleValue(),
y = ( new Double( (String)st.nextElement() ) ).doubleValue();
points.pt[ i ] = new Complex( x, y );
}
catch( java.util.NoSuchElementException ex ) {
System.out.println( "ошибка: " + ex.toString() );
continue;
}
catch( java.lang.NumberFormatException ex ) {
System.out.println( "ошибка: " + ex.toString() );
continue;
}
i++;
}
System.out.println( "треугольник: " + points.toString() );
System.out.println( "периметр = " + points.perimeter() );
System.out.println( "площадь = " + points.square() );
System.out.println( "---------------------------------" );
}
}
}
В Java нет типа комплексных чисел (как его не было и в C 30 лет до стандарта C99). Для нашего приложения реализацию векторных операций, можно решить следующими способами:
1. Написать (прямо в приложении) свои собственные операции над векторами, нам из них всех нужно: разность (-), модуль (abs, cabs), и фазовый угол (arg, carg).
2. Написать свой собственный класс Complex ... это несложно.
3. Заимствовать где-то в сети рукописный тип Complex (а их там миллион ).
Я воспользовался 3-м способом (и это самый правильный путь), и взял реализацию из математического проекта 3D-XplorMath-J (не знаю относительно математики в самом проекте, но реализация комплексной математики там примитивная).
Переходим к компиляции:
Код: Выделить всё
olej@notebook:~/2014_WORK/ManyLan$ javac triangle.java
Код: Выделить всё
olej@notebook:~/2014_WORK/ManyLan$ ls *.class
Complex.class triangle.class Tric.class
Но это, по смыслу, совершенно другая компиляция, чем в случае C/C++!!!
Выполнение (не хотелось возиться с форматирование числа знаков вещественного вывода ):
Код: Выделить всё
olej@notebook:~/2014_WORK/ManyLan$ java triangle
координаты вершин в формате: X Y
вершина № 1 : -1 0
вершина № 2 : 0 1
вершина № 3 : 1 0
треугольник: [-1.0,0.0] [0.0,1.0] [1.0,0.0]
периметр = 4.82842712474619
площадь = 1.0
---------------------------------
координаты вершин в формате: X Y
вершина № 1 :
- Вложения
-
- triangle.java
- (2.44 КБ) 598 скачиваний
-
- Complex.java
- (7.02 КБ) 630 скачиваний
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 3 гостя