برنامه نویسی

چالش بزرگ اعداد اول: کدام زبان برنامه نویسی سریع ترین است؟

برای اینکه تجربه‌ای از سرعت‌های مختلف بین زبان‌های برنامه‌نویسی مختلف داشته باشم، تصمیم گرفتم ببینم زبان‌های مختلف با چه سرعتی اعداد اول بین 1 تا 10000000 را محاسبه و ذخیره می‌کنند. هفت زبانی که من انتخاب می کنم عبارتند از:

  • سی
  • برو
  • جاوا
  • جاوا اسکریپت
  • پایتون
  • روبی
  • زنگ

برای تنظیم این، ابتدا کد پایتون زیر را نوشتم:

import math
from datetime import datetime

def is_prime(num):
    if num < 2:
        return False
    for i in range(2, int(math.sqrt(num)) + 1):
        if num % i == 0:
            return False
    return True

start = datetime.now()
primes = []
for num in range(int(1e7)):
    if is_prime(num):
        primes.append(num)
print('Python: ', datetime.now() - start)
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کد با بررسی اینکه آیا هر یک از اعداد صحیح در محدوده، اول است یا خیر یک عدد صحیح n را تعیین می کند. [2, sqrt(n)] ضریبی با باقیمانده صفر دارد. سپس، از طریق اعداد صحیح در محدوده تکرار می شود [1, 10,000,000]، ذخیره کردن عدد صحیح اگر واقعاً اول باشد.

اگرچه من علاقه ای به مشاهده یا استفاده از لیست اعداد اول ندارم، اما برای ذخیره اطلاعات وارد می شود تا مدیریت حافظه زبان آزمایش شود.

سپس با استفاده از ChatGPT، این کد پایتون را به ۶ زبان دیگر تبدیل کردم.

ج:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <time.h>

bool is_prime(int num) {
    if (num < 2) {
        return false;
    }
    for (int i = 2; i <= sqrt(num); i++) {
        if (num % i == 0) {
            return false;
        }
    }
    return true;
}

int main() {
    clock_t start = clock();
    int *primes = malloc(10000000 * sizeof(int));
    int count = 0;
    for (int num = 2; num < 10000000; num++) { // Start at num=2, not num=0
        if (is_prime(num)) {
            primes[count++] = num;
        }
    }
    printf("C: %f seconds\n", ((double)clock() - start) / CLOCKS_PER_SEC);
    free(primes); // Free the dynamically allocated memory
    return 0;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برو:

package main

import (
    "fmt"
    "math"
    "time"
)

func isPrime(num int) bool {
    if num < 2 {
        return false
    }
    for i := 2; i <= int(math.Sqrt(float64(num))); i++ {
        if num%i == 0 {
            return false
        }
    }
    return true
}

func main() {
    start := time.Now()
    primes := []int{}
    for num := 0; num < int(1e7); num++ {
        if isPrime(num) {
            primes = append(primes, num)
        }
    }
    fmt.Println("Go: ", time.Since(start))
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

جاوا:

import java.time.Duration;
import java.time.Instant;
import java.lang.Math;
import java.util.ArrayList;
import java.util.List;

public class primes {
    public static boolean isPrime(int num) {
        if (num < 2) {
            return false;
        }
        for (int i = 2; i <= Math.sqrt(num); i++) {
            if (num % i == 0) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        Instant start = Instant.now();
        List<Integer> primes = new ArrayList<Integer>();
        for (int num = 0; num < 10000000; num++) {
            if (isPrime(num)) {
                primes.add(num);
            }
        }
        System.out.println("Java: " + Duration.between(start, Instant.now()).toMillis() + " ms");
    }
} 
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

جاوا اسکریپت:

function isPrime(num) {
    if (num < 2) {
      return false;
    }
    for (let i = 2; i <= Math.sqrt(num); i++) {
      if (num % i === 0) {
        return false;
      }
    }
    return true;
  }

  const start = new Date();
  const primes = [];
  for (let num = 0; num < 1e7; num++) {
    if (isPrime(num)) {
      primes.push(num);
    }
  }
  console.log(`JavaScript: ${(new Date() - start)/1000} seconds`);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

یاقوت سرخ:

def is_prime(num)
    return false if num < 2
    (2..Math.sqrt(num).to_i).each do |i|
      return false if num % i == 0
    end
    true
  end

  start = Time.now
  primes = []
  (0...1e7.to_i).each do |num|
    primes << num if is_prime(num)
  end
  puts "Ruby: #{Time.now - start} seconds"
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

زنگ:

use std::time::{Instant, Duration};
use std::f64::consts::SQRT_2;

fn is_prime(num: u32) -> bool {
    if num < 2 {
        return false;
    }
    for i in 2..=((num as f64).sqrt() as u32) {
        if num % i == 0 {
            return false;
        }
    }
    true
}

fn main() {
    let start = Instant::now();
    let mut primes = Vec::new();
    for num in 0..10_000_000 {
        if is_prime(num) {
            primes.push(num);
        }
    }
    let end = Instant::now();
    let time_elapsed = end - start;
    println!("Rust: {:?}", time_elapsed);
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

توضیحات تصویر

زبان مسابقه 1 مسابقه 2 مسابقه 3 میانگین
سی 8.9 ثانیه 8.9 ثانیه 8.9 ثانیه 8.9 ثانیه
برو 11.8 ثانیه 11.6 ثانیه 11.6 ثانیه 11.7 ثانیه
جاوا 4.6 ثانیه 4.7 ثانیه 4.6 ثانیه 4.6 ثانیه
جاوا اسکریپت 4.4 ثانیه 4.4 ثانیه 4.4 ثانیه 4.4 ثانیه
پایتون 99.5 ثانیه 88.9 ثانیه 88.2 ثانیه 92.2 ثانیه
روبی 64.4 ثانیه 68.6 ثانیه 64.4 ثانیه 65.8 ثانیه
زنگ 25.2 ثانیه 25.3 ثانیه 25.3 ثانیه 25.3 ثانیه

برنده: جاوا اسکریپت

کندترین: پایتون (20 برابر کندتر از جاوا اسکریپت)

از این آزمون چه نتیجه ای می توانیم بگیریم؟ خوب، ما چه نمی تواند نتیجه این است که جاوا اسکریپت دو برابر سریعتر از C است و همچنین پایتون 10 برابر کندتر از C است. می توان استنباط کنید که برای محاسبه اعداد اول به این روش، جاوا و جاوا اسکریپت از نظر سرعت گزینه های بسیار خوبی خواهند بود و پایتون و روبی انتخاب های نسبتا ضعیفی خواهند بود. توجه به این نکته مهم است که این فقط آزمایش یک برنامه از این زبان ها بود و تصویر واضحی از کارایی کلی زبان ارائه نمی دهد. واضح است که پایتون و روبی به طور قابل توجهی کندتر از جاوا/جاوا اسکریپت/C هستند، بنابراین شاید بتوان فرض کرد که این زبان ها به طور کلی کندتر هستند. در واقع، یکی از بزرگترین انتقادات پایتون و دلایل عدم استفاده از آن، کند بودن آن است.

یک عامل مهم در بحث سرعت زبان، تایپ استاتیک در مقابل تایپ پویا است. به طور خلاصه، تایپ استاتیک به این معنی است که نوع متغیر در زمان کامپایل بررسی می شود و تایپ پویا به این معنی است که نوع متغیر در زمان اجرا بررسی می شود. زبان‌هایی که به صورت ایستا تایپ می‌شوند عبارتند از C، Go، Java و Rust که جاوا اسکریپت، پایتون و روبی به صورت پویا تایپ می‌شوند.

چرا جاوا اسکریپت بسیار سریعتر از دو زبان دیگر تایپ شده پویا است؟ در حالی که عوامل دیگری به جز تایپ وجود دارد که بر سرعت تأثیر می گذارد، این تفاوت عمدتاً به دلیل مفهومی به نام پیوند جمع آوری Just-In-Time (JIT) است. تا حدی به این دلیل است که جاوا اسکریپت بسیار مورد استفاده و محبوب است که جامعه بزرگ این ویژگی و سایر ویژگی های جاوا اسکریپت را توسعه داده است که به سرعت بخشیدن به آن کمک می کند.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا