Skip to content

billtubbs/lang-comp

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.

Comparison of three high-level programming languages for numerical computing

Objective

Compare the syntax and ease-of-use of these three popular programming languages on basic numerical computation tasks:

Other things not considered here

  • R (www.r-project.org) a high-level language for statistical computing
  • Capabilities of these languages in other applications
  • A comparison of the performance of these languages
  • Maturity of the language, available packages and support community

Language Comparison – Examples

The following sections contain code examples in each language for the following features:

Function definition

Python

def power(x, a):
    return x**a

Julia

function power(x, a)
  x^a
end

# Assignment form
power2(x, a) = x^a

MATLAB

function y = power(x, a)
  y = x^a;
end

% Note: Functions must go at end of the
% file or in a separate file

Anonymous functions

Python

# Lambda function
power = lambda x, a: x**a

Julia

# Anonymous function
power = (x, a) ->  x^a

MATLAB

% Anonymous function
power = @(x, a) x^a

Variable assignment

Python

x = power(2, 0.5)

Julia

x = power(2, 0.5)

MATLAB

x = power(2, 0.5);

Standard output

Python

print(x)

# Output:
# 1.4142135623730951

Julia

println(x)

# Output:
# 1.4142135623

MATLAB

disp(x)

% Output:
%   1.4142

% Or omit the line terminator
x = power(2, 0.5)

% Output:
% 
% x =
% 
%     1.4142
% 

Formatted output

Python

# Since Python 3.4
print("{:5.2f}".format(x))

# Since Python 3.6
print(f"{x:5.2f}")

# 'Old style'
print("%5.2f" % x)

# Output:
#  1.41
#  1.41
#  1.41

Julia

using Printf

@printf("%5.2f\n", x)

# Output:
#  1.41

MATLAB

fprintf("%5.2f\n", x)

% Output:
%  1.41

Definite loop

Python

for i in range(5):
    print(i)

# Output:
# 0
# 1
# 2
# 3
# 4

Julia

for i in 1:5
  println(i)
end

# Output:
# 1
# 2
# 3
# 4
# 5

MATLAB

for i=1:5
  disp(i)
end

% Output:
%      1
% 
%      2
% 
%      3
% 
%      4
% 
%      5
% 

Indefinite loop

Python

i = 0
while i < 5:
    print(i)
    i += 1

# Output:
# 0
# 1
# 2
# 3
# 4

Julia

i = 1
while i <= 5
  println(i)
  global i += 1
end

# Output:
# 1
# 2
# 3
# 4
# 5

MATLAB

i = 1;
while i <= 5
  disp(i)
  i = i + 1;
end

% Output:
%      1
% 
%      2
% 
%      3
% 
%      4
% 
%      5
% 

Lists

Python

symbols = ['H', 'He', 'Li']
print(symbols)

# Output:
# ['H', 'He', 'Li']

Julia

symbols = ["H", "He", "Li"]  # Array
println(symbols)

# Output
# ["H", "He", "Li"]

MATLAB

symbols = {'H','He','Li'}  % Cell array

% Output:
% 
% symbols =
% 
%   1Ă—3 cell array
% 
%     {'H'}    {'He'}    {'Li'}
% 

Dictionaries

Python

elements = {
    'H': 1,
    'He': 2, 
    'Li': 3
}
print(elements)

# Output:
# {'H': 1, 'He': 2, 'Li': 3}

Julia

elements = Dict(
    "H" => 1,
    "He" => 2, 
    "Li" => 3
)
println(elements)

# Output
# Dict("Li"=>3,"He"=>2,"H"=>1)

MATLAB

symbols = {'H','He','Li'};  % numeric or cell arrays only
values = [1 2 3];
elements = containers.Map(symbols,values)

% Output:
% 
% elements = 
% 
%   Map with properties:
% 
%         Count: 3
%       KeyType: char
%     ValueType: double
% 

Iterating over collections

Python

for symbol, n in elements.items():
    print(f"{symbol}: {n}")

# Output:
# H: 1
# He: 2
# Li: 3

Julia

for (symbol, n) in elements
  @printf("%s: %d\n", symbol, n)
end

# Output:
# H: 1
# He: 2
# Li: 3

MATLAB

for symbol = keys(elements)
    n = elements(symbol{1});
    fprintf("%s: %d\n", symbol{1}, n)
end

% Output:
% H: 1
% He: 2
% Li: 3

Array literals

Python

import numpy as np

# Vector (1d)
x = np.array([1, 2, 3])

# Matrix (2d)
A = np.array([[1, 2],
              [3, 4],
              [5, 6]])

# 3d array (3x2x3)
Z = np.ones((3, 2, 3))

print(x)
print(A)
print(Z)

# Output:
# [1 2 3]
# [[1 2]
#  [3 4]
#  [5 6]]
# array([[[1., 1., 1.],
#         [1., 1., 1.]],
# 
#        [[1., 1., 1.],
#         [1., 1., 1.]],
# 
#        [[1., 1., 1.],
#         [1., 1., 1.]]])
# 

Julia

# Vector (1d)
x = [1, 2, 3]
println(x)

# Matrix (2d)
A = [1 2; 3 4; 5 6]
println(A)

# 3d array (3x2x3)
Z = ones(3, 2, 3)

println(x)
println(A)
println(Z)

# Output:
# [1, 2, 3]
# [1 2; 3 4; 5 6]
# [1.0 1.0; 1.0 1.0; 1.0 1.0]
# 
# [1.0 1.0; 1.0 1.0; 1.0 1.0]
# 
# [1.0 1.0; 1.0 1.0; 1.0 1.0]
# 

MATLAB

% Row vector (2d)
x = [1 2 3]  % or x = [1, 2, 3]

% Matrix (2d)
A = [1 2; 3 4; 5 6]

% 3d array (3x2x3)
Z = ones(3, 2, 3)

% Output
% 
% x =
% 
%      1     2     3
% 
% 
% A =
% 
%      1     2
%      3     4
%      5     6
% 
% 
% Z(:,:,1) =
% 
%      1     1
%      1     1
%      1     1
% 
% 
% Z(:,:,2) =
% 
%      1     1
%      1     1
%      1     1
% 
% 
% Z(:,:,3) =
% 
%      1     1
%      1     1
%      1     1
% 

Array dimensions

Python

import numpy as np

# Vector (1d)
x = np.array([1, 2, 3])

# Matrix (2d)
A = np.array([[1, 2],
              [3, 4],
              [5, 6]])

# 3d array (3x2x3)
Z = np.ones((3, 2, 3))

print(x.shape)
print(A.shape)
print(Z.shape)

# Output:
# (3,)
# (3, 2)
# (3, 2, 3)

Julia

# Vector (1d)
x = [1, 2, 3]

# Matrix (2d)
A = [1 2; 3 4; 5 6]

# 3d array (3x2x3)
Z = ones(3, 2, 3)

println(size(x))
println(size(A))
println(size(Z))

# Output:
# (3,)
# (2, 3)
# (3, 2, 3)

MATLAB

% Row vector (2d)
x = [1 2 3]  % or x = [1, 2, 3]

% Matrix (2d)
A = [1 2; 3 4; 5 6]

% 3d array (3x2x3)
Z = ones(3, 2, 3)

size(x)
size(A)
size(Z)

% Output
% 
% ans =
% 
%      1     3
% 
% 
% ans =
% 
%      3     2
% 
% 
% ans =
% 
%      3     2     3
% 

Indexing arrays

Python

# Vector (1d)
x = np.array([1, 2, 3])

# Matrix (2d)
A = np.array([[1, 2],
              [3, 4],
              [5, 6]])

print(x[1])
print(A[1,1])
print(A[1])

# Output:
# 2
# 4
# [3 4]

Julia

# Vector (1d)
x = [1, 2, 3]

# Matrix (2d)
A = [1 2; 3 4; 5 6]

println(x[2])
println(A[2,2])
println(A[2])

# Output:
# 2
# 4
# 3

MATLAB

% Row vector (2d)
x = [1 2 3]  % or x = [1, 2, 3]

% Matrix (2d)
A = [1 2; 3 4; 5 6]

x(2)
A(2,2)
A(2)


% Output
% 
% ans =
% 
%      2
% 
% 
% ans =
% 
%      4
% 
% 
% ans =
% 
%      3
% 

Slicing arrays

Python

# Vector (1d)
x = np.array([1, 2, 3])

# Matrix (2d)
A = np.array([[1, 2],
              [3, 4],
              [5, 6]])

print(x[1:])
print(A[:,1])

# Output:
# [2 3]
# [2 4 6]

Julia

# Vector (1d)
x = [1, 2, 3]

# Matrix (2d)
A = [1 2; 3 4; 5 6]

println(x[2:end])
println(A[:,2])

# Output:
# [2, 3]
# [2, 4, 6]

MATLAB

% Row vector (2d)
x = [1 2 3]  % or x = [1, 2, 3]

% Matrix (2d)
A = [1 2; 3 4; 5 6]

x(2:end)
A(:,2)

% Output
% 
% ans =
% 
%      2     3
% 
% 
% ans =
% 
%      2
%      4
%      6
% 

Array concatenation

Python

# Vector (1d)
x = np.array([1, 2, 3])

# Matrix (2d)
A = np.array([[1, 2],
              [3, 4],
              [5, 6]])

# Concatenation of vector and 2-d array
C = np.hstack([x.reshape(-1, 1), A])
# or
C = np.column_stack([x, A])
print(C)

# Output:
# [[1 1 2]
#  [2 3 4]
#  [3 5 6]]

Julia

# Vector (1d)
x = [1, 2, 3]
println(x)

# Matrix (2d)
A = [1 2; 3 4; 5 6]
println(A)

# Concatenation of vector and 2-d array
C = [x A]
println(C)

# Output
# [1 1 2; 2 3 4; 3 5 6]

MATLAB

% Row vector (2d)
x = [1 2 3]  % or x = [1, 2, 3]

% Matrix (2d)
A = [1 2; 3 4; 5 6]

% Concatenation of vector and 2-d array
C = [x' A]

% Output
% 
% C =
% 
%      1     1     2
%      2     3     4
%      3     5     6
% 

Array broadcasting

Python

# Vector (1d)
x = np.array([1, 2, 3])

# Matrix (2d)
A = np.array([[1, 2],
              [3, 4],
              [5, 6]])

# Array broadcasting
print(1 - A)
print(A + x.reshape(-1, 1))

# Output:
# [[ 0 -1]
#  [-2 -3]
#  [-4 -5]]
# [[2 3]
#  [5 6]
#  [8 9]]

Julia

# Row vector (2d)
x = [1 2 3]

# Matrix (2d)
A = [1 2; 3 4; 5 6]

println(1 .- A)
println(A .+ x)

# Output:
# [0 -1; -2 -3; -4 -5]
# [2 3; 5 6; 8 9]

MATLAB

% Row vector (2d)
x = [1 2 3]  % or x = [1, 2, 3]

% Matrix (2d)
A = [1 2; 3 4; 5 6]

1-A
A+x'

% Output
% 
% ans =
% 
%      0    -1
%     -2    -3
%     -4    -5
% 
% 
% ans =
% 
%      2     3
%      5     6
%      8     9
% 

Linear algebra

Python

import numpy as np

A = np.array([[0.8, 0], [0, 1]])
K = np.array([[0.942], [1.074]])
C = np.array([[0.2, 1]])

# Matrix inverse
# Since Python 3.5
X = np.linalg.inv(np.eye(2) - A + K @ C)
# Prior to 3.5
X = np.linalg.inv(np.eye(2) - A + K.dot(C))

print(X)

# Output:
# [[ 5.         -4.38547486]
#  [-1.          1.80819367]]

Julia

using LinearAlgebra

A = [0.8 0; 0 1];
K = [0.942; 1.074];
C = [0.2 1];

# Matrix inverse
X = (I - A + K*C)^-1

println(X)

# Output:
# [5.000000000000001 -4.385474860335195; -1.0000000000000002 1.808193668528864]

MATLAB

A = [0.8 0; 0 1]; 
K = [0.942; 1.074]; 
C = [0.2 1];

% Matrix inverse
X = (eye(2) - A + K*C)^-1

% Output
% 
% ans =
% 
%     5.0000   -4.3855
%    -1.0000    1.8082
% 

Symbolic Math

Python

from sympy import symbols, solve, diff
a, b, c, x = symbols('a b c x')
y = a*x**2 + b*x + c
dydx = diff(y, x)
x_sol = solve(dydx, x)
y_sol = y.subs(x, x_sol[0])
print(dydx)
print(x_sol)
print(y_sol)

# Output:
# 2*a*x + b
# [-b/(2*a)]
# c - b**2/(4*a)

Julia

y = :(a*x^2 + b*x + c)  # Symbolic expressions are built in
using Reduce
dydx = Algebra.df(y,:x)
x_sol = Algebra.solve(dydx,:x)
y_sol = Algebra.sub(x_sol,y)
println(dydx)
println(x_sol)
println(y_sol)

# Output:
# 2 * a * x + b
# (:(x = -b / (2a)),)
# (4 * a * c - b ^ 2) / (4a)

MATLAB

syms a b c x
y = a*x^2 + b*x + c;
dydx = diff(y,x)
x_sol = solve(dydx,x)
y_sol = subs(y,x,x_sol)

% Output
% 
% dydx =
%  
% b + 2*a*x
%  
%  
% x_min =
%  
% -b/(2*a)
%  
%  
% y_min =
%  
% - b^2/(4*a) + c
%  

About

Comparison of high-level programming languages for numerical computing.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published