易語言效率與C++究竟差多少(質數和計算)

Icys發表於2021-08-13

文字首發bIlibilicnblogs為作者補發,如在其他平臺看見本文,均為經允許的盜竊

易語言作為款主打 中文 易用 程式設計的開發軟體。但是很多人都在批評易語言的效率。
我們今天通過 質數和計算 來看看易語言的效率到底與C++差了多少。

話不多說,這是今天的測試平臺

  1. C++部分
  2. 開發環境VC++ 2019
  3. Release x86
  4. 程式碼優化為 /O2

C++程式碼(原本V2IDX是內聯的,但是易語言不支援,為了達到一樣的效果,我取消了)
其餘微小差異均已忽略

程式碼源自知乎大神@wjhbb
原帖

#include <math.h>
#include <stdio.h>
#include <assert.h>
#include <iostream>
#include <windows.h>
#define LINT long long

LINT V2IDX(LINT v, LINT N, LINT Ndr, LINT nv) {

     return v >= Ndr ? (N / v - 1) : (nv - v);
}

LINT primesum(LINT N) {

    LINT* S;
    LINT* V;
    LINT r = (LINT)sqrt(N);
    LINT Ndr = N / r;
    assert(r * r <= N and (r + 1) * (r + 1) > N);
    LINT nv = r + Ndr - 1;
     V = new LINT[nv];
    S = new LINT[nv];
    for (LINT i = 0; i < r; i++) {
        V[i] = N / (i + 1);
    }
    for (LINT i = r; i < nv; i++) {
        V[i] = V[i - 1] - 1;
    }
    for (LINT i = 0; i < nv; i++) {
        S[i] = V[i] * (V[i] + 1) / 2 - 1;
    }
    for (LINT p = 2; p <= r; p++) {
        if (S[nv - p] > S[nv - p + 1]) {
            LINT sp = S[nv - p + 1];
            LINT p2 = p * p;
            for (LINT i = 0; i < nv; i++) {
                if (V[i] >= p2) {
                    S[i] -= p * (S[V2IDX(V[i] / p, N, Ndr, nv)] - sp);
                }
                else {
                    break;
                }
            }
        }
    }
    return S[0];
}

int main() {
    using std::cin;
    printf("請輸入您要求的質數和的上限:" );
    LINT N ;
    cin >> N;
    int t = GetTickCount();
    printf("%lld\n", primesum(N));
    printf("耗時(ms)%u", GetTickCount() - t);
    cin >> N;
}

易語言部分

  1. 開發環境 易語言5.9
  2. 分別比較 動態編譯 靜態編譯(VC98Linker) 黑月編譯(VC14.23Linker,C/C++方式編譯)
  3. 開啟快速陣列訪問,不插入花指令,不打亂編譯結果.
​.版本 2

.程式集 Main

.子程式 _啟動子程式, 整數型, , 本子程式在程式啟動後最先執行
.區域性變數 N, 長整數型
.區域性變數 t, 整數型

標準輸出 (, “請輸入您要求的質數和的上限:”)
N = 到長整數 (標準輸入 ())
t = GetTickCount ()
標準輸出 (, 到文字 (Primesum (N)) + #換行符)
標準輸出 (, “耗時(ms)” + 到文字 (GetTickCount () - t))
標準輸入 ()
返回 (0)  ' 可以根據您的需要返回任意數值

.子程式 V2IDX, 長整數型
.引數 V, 長整數型
.引數 N, 長整數型
.引數 Ndr, 長整數型
.引數 nv, 長整數型

.如果真 (V ≥ Ndr)
    返回 (N ÷ V - 1)
.如果真結束
返回 (nv - V)
.版本 2

.子程式 Primesum, 長整數型
.引數 N, 長整數型

.區域性變數 S, 長整數型, , "0"
.區域性變數 V, 長整數型, , "0"
.區域性變數 r, 長整數型
.區域性變數 Ndr, 長整數型
.區域性變數 nv, 長整數型
.區域性變數 i, 長整數型
.區域性變數 p, 長整數型
.區域性變數 sp, 長整數型
.區域性變數 p2, 長整數型

r = 求平方根 (N)

Ndr = N ÷ r

nv = r + Ndr - 1

重定義陣列 (V, 假, nv)
重定義陣列 (S, 假, nv)

i = 0

.判斷迴圈首 (i < r)
    V [i + 1] = N ÷ (i + 1)
    i = i + 1

.判斷迴圈尾 ()

i = r

.判斷迴圈首 (i < nv)
    V [i + 1] = V [i] - 1
    i = i + 1
.判斷迴圈尾 ()

i = 0

.判斷迴圈首 (i < nv)
    S [i + 1] = V [i + 1] × (V [i + 1] + 1) ÷ 2 - 1
    i = i + 1
.判斷迴圈尾 ()

p = 2

.判斷迴圈首 (p ≤ r)
    .如果真 (S [nv - p + 1] > S [nv - p + 2])
        sp = S [nv - p + 2]
        p2 = p × p
        i = 0

        .判斷迴圈首 (i < nv)
            .如果 (V [i + 1] ≥ p2)
                S [i + 1] = S [i + 1] - p × (S [V2IDX (V [i + 1] ÷ p, N, Ndr, nv) + 1] - sp)
            .否則
                跳出迴圈 ()
            .如果結束
            i = i + 1
        .判斷迴圈尾 ()
    .如果真結束
    p = p + 1
.判斷迴圈尾 ()
返回 (S [1])

UP翻譯的程式碼不是很好,歡迎大家指正.

PS:GetTickCount()得到的時間差可能不會很準.,同時我也承認這樣比較方法的不嚴謹性,所以測試結果僅供參考.

順帶提一下電腦CPU是i7-7700k

編譯生成後
可以發現C++的體積是最小的(易語言動態編譯的還要帶幾個支援庫檔案)

可以發現C++的體積是最小的(易語言動態編譯的還要帶幾個支援庫檔案)

先從一億以內的質數開始
可以發現他們之間的速度差距

可以發現他們之間的速度差距

當我們提高計算量時,我們會驚人的發現 易語言程式算錯了
例如知乎上的10億

易語言算的慢也就算了,關鍵還是不精確的

UP嘗試發現原因,覺得可能是一下幾點

  1. UP技術太垃圾翻譯了
  2. UP主的盜版易語言的暗裝沒清乾淨
  3. 易語言的陣列只支援到INT的成員數
  4. 易語言的數值轉換問題

請大神們看看是什麼情況.UP也不好妄下定論。

但是起碼證明了一點,沒有不好的程式語言,只有效率低下的演算法,在1億以內易語言還是有準確性的.如果其他程式語言用的演算法比易語言低效,那也不見的比易語言快的.(UP用的演算法也不一定是最快的演算法).易語言作為一個怡情使用的開發軟體還是很不錯的.
聽說易語言創始人吳濤將要為他的火山開發平臺新增PC端的開發功能,讓我們拭目以待.(UP在考慮要不要要火山上補個票)

相關文章