20191230のGoに関する記事は7件です。

眺めて覚えるGo言語 その7 GO言語の中にC言語

GO言語の中にC言語を書いてみよう。

準備 GCCをインストールしておきます。

  • Windows 10 64bitの場合
  • mingw-w64-install.exeをインストールします。 image.png x86_64を選択します。 最初の一歩は、いつもの Hello World
cPrint.go
package main

// #include <stdio.h>
// #include <stdlib.h>
//
// static void cprint(char* s) {
//   printf("%s\n", s);
// }
import "C"
import "unsafe"

func main() {
    cs := C.CString("Hello World C")
    C.cprint(cs)
    C.free(unsafe.Pointer(cs))
}

//のコメント部分にC言語でコーディングします。

  • 上記の例は、cprint関数を定義してprintfを呼び出しています。
  • Cのfree関数を呼んでいます。
  • 上記に必要なincludeを

1 stdio.h printf
2 stdlib.h free
で行っています。

>go run cprint.go
Hello World C

配列を渡して合計を求める。(int *)版

sum.go
package main

// int cal_sum(int *x,int n) {
// int sum=0;
//  for(int i=0;i<n;i++){
//      sum+=x[i];
//  }
// return sum;
//}
import "C"
import "fmt"

func main() {
    x := []C.int{1, 2, 3, 4,5,6,7,8,9,10}
    a:=C.cal_sum((*C.int)(&x[0]),(C.int)(len(x)))
    fmt.Println("sigma x=",a)
}

>go run sum.go
sigma x= 55

配列を渡して合計を求める。(float *)版

sigma.go
package main

// float cal_sum(float *x,int n) {
// float sum=0.0;
//  for(int i=0;i<n;i++){
//      sum+=x[i];
//  }
// return sum;
//}
import "C"
import "fmt"

func main() {
    x := []C.float{10.0, 20.0, 30.0, 40.0,50.0,60.0,70.0,80.0,90.0,100.0}
    a:=C.cal_sum((*C.float)(&x[0]),(C.int)(len(x)))
    fmt.Println("sigma x=",a)
}

配列を渡して平均を求める。(float *)版

avr.go
package main

// float cal_sum(float *x,int n) {
// float sum=0.0;
//  for(int i=0;i<n;i++){
//      sum+=x[i];
//  }
// return sum/n;
//}
import "C"
import "fmt"

func main() {
    x := []C.float{10.0, 20.0, 30.0, 40.0,50.0,60.0,70.0,80.0,90.0,100.0}
    a:=C.cal_sum((*C.float)(&x[0]),(C.int)(len(x)))
    fmt.Println("avr a=",a)
}

>go run avr.go
avr a= 55

CGOは、なかなか便利な仕組みです。

  • C言語が使えれば容易にI/Oなどにアクセスするインターフェースを書くことができる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

goでBazelを使うメリット

TL;DR

  • 基本bazelは遅い, というかgoコマンドが速すぎる
  • goコマンド しか使わないならば、bazelは使わない方がいい
  • もし、go-bindataやstatik, gomockなど、ビルドの途中にコマンドを打つ必要がある場合は、アリかもしれない。
  • モノレポの場合はアリかもしれない

Bazel

https://bazel.build/
Googleが開発してるビルドツールです。 現在、最も使われてるのはmakeだと思うのですが、makeの問題点としては、Makefileに全部書けば、かなり、長いコードになってしまい、メンテナンスしにくかったり、結局、シェルを他で書いて呼び出したりって感じになっちゃうんです。
そこで、Bazelはビルドルールというライブラリ的なやつを使えまして、例えば、golangですと、go_libraryとgo_binaryというビルドルールを使って下のようにBUILD.bazelに書けばビルドしてくれます。

また、makeでは --jobs で並列処理してましたが、 bazelでは、うまいこと依存関係を解析して、並列処理でビルドしてくれます。

BUILD.bazel
go_library(
    name = "go_default_library",
    srcs = ["main.go"],
    importpath = "github.com/...",
    deps = [
        ...
    ],
)

go_binary(
    name = "apiserver",
    embed = [":go_default_library"],
    visibility = ["//visibility:public"],
)

Gazelle

先ほどのBUILD.bazelをいちいち一つずつ書くなら、Makefileの方が良いですよね、なので、これらのルールを自動で作ってくれるやつが存在します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Golang + Lambda + API Gateway】で、S3バケットを作るAPIを作ってみた

lambda(qiita).png

前提条件

2019年12月29日に試してみたものです。
Go 1.12.9

1. GolangのコードをLambdaで実行

必要なライブラリをインストール

$ go get -u github.com/aws/aws-lambda-go/lambda
$ go get -u github.com/aws/aws-sdk-go/...

指定したバケット名で、S3バケットを作るコード

作った関数は、引数として受け取ったバケット名で、S3バケットを作り、その結果をログに出力するもの。

hello.go
package main

import (
    "log"

    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/credentials"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
)

type MyEvent struct {
    BucketName string `json:"bucket_name"`
}

func hello(event MyEvent) {
    // 流れ:認証情報→セッション→S3
    creds := credentials.NewStaticCredentials("AWS_ACCESS_KEY", "AWS_SECRET_ACCESS_KEY", "") //第3引数はtoken
    session, _ := session.NewSession(&aws.Config{
        Credentials: creds,
        Region:      aws.String("ap-northeast-1")},
    )
    svc := s3.New(session)
    resp, _ := svc.CreateBucket(&s3.CreateBucketInput{
        Bucket: aws.String(event.BucketName),
    })
    log.Println(resp) //Lambdaテストの実行結果のログ出力や、CloudWatchのロググループで確認できる
}

func main() {
    lambda.Start(hello)
}

ビルド(クロスコンパイル)して、zipファイルにする

Lambdaで動かすためには、普通にgo buildするのではなく、Linux上でも動作するようにクロスコンパイルの設定を追加する必要がある

$ GOOS=linux GOARCH=amd64 go build -o hello
$ zip handler.zip ./hello

zipファイルをLambdaにアップロード

  1. Lambdaコンソールから関数を作成し、上記で作成したZIPファイルをアップロード
  2. Lambdaの関数コードのハンドラは、作成した関数名と一致させる(本記事ではhello)
  3. 忘れずに保存ボタン

テスト(動作確認)

  • Lambdaコンソールの「テストイベントの設定」画面で、下記のjsonデータを入力
  • S3バケット名になるため、一意になる名前を指定
{
  "bucket_name": "test191229" 
}
  • S3コンソールで、指定したバケット名で作られているか確認
  • ログ出力を確認 → 成功した場合、「Location」(S3のURL)が返ってくる

2. API GatewayでAPI作成

  1. API Gatewayコンソールから「APIの作成」→REST APIの「構築」ボタン
  2. API名を入力し、API作成
  3. アクション→「リソースの作成」(リソース名は、アクセスするパスになるので注意
  4. アクション→「メソッドの作成」(GETを指定し、作ったLambda関数を指定)
  5. 「メソッドリクエスト」→「URLクエリ文字列パラメータ」を追加(bucket_name)
  6. 「マッピングテンプレートの追加」(Content-Type:application/json)
  7. 「テンプレートの生成」→emptyにし、以下を入力
#set($inputRoot = $input.path('$'))
{
    "bucket_name" : "$input.params('bucket_name')"
}

 ※上記が、作成したhello関数の引数として入ってくる

$input.params(x)

パラメータ名文字列 x が指定された場合に、パス、クエリ文字列、またはヘッダー値から (この順番で検索される) メソッドリクエストパラメータの値を返します。

マッピングテンプレートで使える変数・関数
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#input-variable-reference

8.最後に、「アクション」→「APIのデプロイ」(ここで入力するステージも、アクセスするパスになるので注意

アクセスするURL

  • 「APIのデプロイ」後、Lambdaコンソールに表示されるURLを利用
  • 例えば、ステージ名が「stage」、リソース名が「myresource」、「URLクエリ文字列パラメータ」が「bucket_name」の場合、
    URL/stage/myresource?bucket_name=test191230

  • ここにアクセスすると、「test191230」というS3バケットが作成される

参考にさせて頂いた記事

AWS Lambda で Go が使えるようになったので試してみた
golang + Lambda + API GatewayでREST APIを作ってみた
AWS SDK for Go S3バケット基本操作

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

golang + Lambda + API Gatewayで、S3バケットを作るAPI作ってみた

前提条件

2019年12月29日に試してみたものです。
go 1.29

1. GolangのコードをLambdaで実行

必要なライブラリをインストール

$ go get -u github.com/aws/aws-lambda-go/lambda
$ go get -u github.com/aws/aws-sdk-go/aws
$ go get -u github.com/aws/aws-sdk-go/aws/credentials
$ go get -u github.com/aws/aws-sdk-go/aws/session
$ go get -u github.com/aws/aws-sdk-go/service/s3

指定したバケット名で、S3バケットを作るコード

作った関数は、引数として受け取ったバケット名で、S3バケットを作り、その結果をログに出力するもの。

hello.go
package main

import (
    "log"

    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/credentials"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
)

type MyEvent struct {
    BucketName string `json:"bucket_name"`
}

func hello(event MyEvent) {
    // 流れ:認証情報→セッション→S3
    creds := credentials.NewStaticCredentials("AWS_ACCESS_KEY", "AWS_SECRET_ACCESS_KEY", "") //第3引数はtoken
    session, _ := session.NewSession(&aws.Config{
        Credentials: creds,
        Region:      aws.String("ap-northeast-1")},
    )
    svc := s3.New(session)
    resp, _ := svc.CreateBucket(&s3.CreateBucketInput{
        Bucket: aws.String(event.BucketName),
    })
    log.Println(resp) //Lambdaテストの実行結果のログ出力や、CloudWatchのロググループで確認できる
}

func main() {
    lambda.Start(hello)
}

ビルド(クロスコンパイル)して、zipファイルにする

$ GOOS=linux GOARCH=amd64 go build -o hello
$ zip handler.zip ./hello

zipファイルをLambdaにアップロード

  1. Lambdaコンソールから関数を作成し、上記で作成したZIPファイルをアップロード
  2. Lambdaの関数コードのハンドラは、作成した関数名と一致させる(本記事ではhello)
  3. 忘れずに保存ボタン

テスト(動作確認)

  • Lambdaコンソールの「テストイベントの設定」画面で、下記のjsonデータを入力
  • S3バケット名になるため、一意になる名前を指定
{
  "bucket_name": "test191229" 
}
  • S3コンソールで、指定したバケット名で作られているか確認
  • ログ出力を確認 → 成功した場合、「Location」(S3のURL)が返ってくる

2. API GatewayでAPI作成

  1. API Gatewayコンソールから「APIの作成」→REST APIの「構築」ボタン
  2. API名を入力し、API作成
  3. アクション→「リソースの作成」(リソース名は、アクセスするパスになるので注意
  4. アクション→「メソッドの作成」(GETを指定し、作ったLambda関数を指定)
  5. 「メソッドリクエスト」→「URLクエリ文字列パラメータ」を追加(bucket_name)
  6. 「マッピングテンプレートの追加」(Content-Type:application/json)
  7. 「テンプレートの生成」→emptyにし、以下を入力
#set($inputRoot = $input.path('$'))
{
    "bucket_name" : "$input.params('bucket_name')"
}

 ※上記が、作成したhello関数の引数として入ってくる

$input.params(x)

パラメータ名文字列 x が指定された場合に、パス、クエリ文字列、またはヘッダー値から (この順番で検索される) メソッドリクエストパラメータの値を返します。

マッピングテンプレートで使える変数・関数
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#input-variable-reference

8.最後に、「アクション」→「APIのデプロイ」(ここで入力するステージも、アクセスするパスになるので注意

アクセスするURL

  • 「APIのデプロイ」後、Lambdaコンソールに表示されるURLを利用
  • 例えば、ステージ名が「stage」、リソース名が「myresource」、「URLクエリ文字列パラメータ」が「bucket_name」の場合、
    URL/stage/myresource?bucket_name=test191230

  • ここにアクセスすると、「test191230」というS3バケットが作成される

参考にさせて頂いた記事

AWS Lambda で Go が使えるようになったので試してみた
golang + Lambda + API GatewayでREST APIを作ってみた
AWS SDK for Go S3バケット基本操作

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

golang + Lambda + API Gatewayで、S3バケットを作るAPIを作ってみた

前提条件

2019年12月29日に試してみたものです。
go 1.29

1. GolangのコードをLambdaで実行

必要なライブラリをインストール

$ go get -u github.com/aws/aws-lambda-go/lambda
$ go get -u github.com/aws/aws-sdk-go/aws
$ go get -u github.com/aws/aws-sdk-go/aws/credentials
$ go get -u github.com/aws/aws-sdk-go/aws/session
$ go get -u github.com/aws/aws-sdk-go/service/s3

指定したバケット名で、S3バケットを作るコード

作った関数は、引数として受け取ったバケット名で、S3バケットを作り、その結果をログに出力するもの。

hello.go
package main

import (
    "log"

    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/credentials"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
)

type MyEvent struct {
    BucketName string `json:"bucket_name"`
}

func hello(event MyEvent) {
    // 流れ:認証情報→セッション→S3
    creds := credentials.NewStaticCredentials("AWS_ACCESS_KEY", "AWS_SECRET_ACCESS_KEY", "") //第3引数はtoken
    session, _ := session.NewSession(&aws.Config{
        Credentials: creds,
        Region:      aws.String("ap-northeast-1")},
    )
    svc := s3.New(session)
    resp, _ := svc.CreateBucket(&s3.CreateBucketInput{
        Bucket: aws.String(event.BucketName),
    })
    log.Println(resp) //Lambdaテストの実行結果のログ出力や、CloudWatchのロググループで確認できる
}

func main() {
    lambda.Start(hello)
}

ビルド(クロスコンパイル)して、zipファイルにする

Lambdaで動かすためには、普通にgo buildするのではなく、Linux上でも動作するようにクロスコンパイルの設定を追加する必要がある

$ GOOS=linux GOARCH=amd64 go build -o hello
$ zip handler.zip ./hello

zipファイルをLambdaにアップロード

  1. Lambdaコンソールから関数を作成し、上記で作成したZIPファイルをアップロード
  2. Lambdaの関数コードのハンドラは、作成した関数名と一致させる(本記事ではhello)
  3. 忘れずに保存ボタン

テスト(動作確認)

  • Lambdaコンソールの「テストイベントの設定」画面で、下記のjsonデータを入力
  • S3バケット名になるため、一意になる名前を指定
{
  "bucket_name": "test191229" 
}
  • S3コンソールで、指定したバケット名で作られているか確認
  • ログ出力を確認 → 成功した場合、「Location」(S3のURL)が返ってくる

2. API GatewayでAPI作成

  1. API Gatewayコンソールから「APIの作成」→REST APIの「構築」ボタン
  2. API名を入力し、API作成
  3. アクション→「リソースの作成」(リソース名は、アクセスするパスになるので注意
  4. アクション→「メソッドの作成」(GETを指定し、作ったLambda関数を指定)
  5. 「メソッドリクエスト」→「URLクエリ文字列パラメータ」を追加(bucket_name)
  6. 「マッピングテンプレートの追加」(Content-Type:application/json)
  7. 「テンプレートの生成」→emptyにし、以下を入力
#set($inputRoot = $input.path('$'))
{
    "bucket_name" : "$input.params('bucket_name')"
}

 ※上記が、作成したhello関数の引数として入ってくる

$input.params(x)

パラメータ名文字列 x が指定された場合に、パス、クエリ文字列、またはヘッダー値から (この順番で検索される) メソッドリクエストパラメータの値を返します。

マッピングテンプレートで使える変数・関数
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#input-variable-reference

8.最後に、「アクション」→「APIのデプロイ」(ここで入力するステージも、アクセスするパスになるので注意

アクセスするURL

  • 「APIのデプロイ」後、Lambdaコンソールに表示されるURLを利用
  • 例えば、ステージ名が「stage」、リソース名が「myresource」、「URLクエリ文字列パラメータ」が「bucket_name」の場合、
    URL/stage/myresource?bucket_name=test191230

  • ここにアクセスすると、「test191230」というS3バケットが作成される

参考にさせて頂いた記事

AWS Lambda で Go が使えるようになったので試してみた
golang + Lambda + API GatewayでREST APIを作ってみた
AWS SDK for Go S3バケット基本操作

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Golang + Lambda + API Gatewayで、S3バケットを作るAPIを作ってみた

前提条件

2019年12月29日に試してみたものです。
Go 1.12.9

1. GolangのコードをLambdaで実行

必要なライブラリをインストール

$ go get -u github.com/aws/aws-lambda-go/lambda
$ go get -u github.com/aws/aws-sdk-go/aws
$ go get -u github.com/aws/aws-sdk-go/aws/credentials
$ go get -u github.com/aws/aws-sdk-go/aws/session
$ go get -u github.com/aws/aws-sdk-go/service/s3

指定したバケット名で、S3バケットを作るコード

作った関数は、引数として受け取ったバケット名で、S3バケットを作り、その結果をログに出力するもの。

hello.go
package main

import (
    "log"

    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/credentials"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
)

type MyEvent struct {
    BucketName string `json:"bucket_name"`
}

func hello(event MyEvent) {
    // 流れ:認証情報→セッション→S3
    creds := credentials.NewStaticCredentials("AWS_ACCESS_KEY", "AWS_SECRET_ACCESS_KEY", "") //第3引数はtoken
    session, _ := session.NewSession(&aws.Config{
        Credentials: creds,
        Region:      aws.String("ap-northeast-1")},
    )
    svc := s3.New(session)
    resp, _ := svc.CreateBucket(&s3.CreateBucketInput{
        Bucket: aws.String(event.BucketName),
    })
    log.Println(resp) //Lambdaテストの実行結果のログ出力や、CloudWatchのロググループで確認できる
}

func main() {
    lambda.Start(hello)
}

ビルド(クロスコンパイル)して、zipファイルにする

Lambdaで動かすためには、普通にgo buildするのではなく、Linux上でも動作するようにクロスコンパイルの設定を追加する必要がある

$ GOOS=linux GOARCH=amd64 go build -o hello
$ zip handler.zip ./hello

zipファイルをLambdaにアップロード

  1. Lambdaコンソールから関数を作成し、上記で作成したZIPファイルをアップロード
  2. Lambdaの関数コードのハンドラは、作成した関数名と一致させる(本記事ではhello)
  3. 忘れずに保存ボタン

テスト(動作確認)

  • Lambdaコンソールの「テストイベントの設定」画面で、下記のjsonデータを入力
  • S3バケット名になるため、一意になる名前を指定
{
  "bucket_name": "test191229" 
}
  • S3コンソールで、指定したバケット名で作られているか確認
  • ログ出力を確認 → 成功した場合、「Location」(S3のURL)が返ってくる

2. API GatewayでAPI作成

  1. API Gatewayコンソールから「APIの作成」→REST APIの「構築」ボタン
  2. API名を入力し、API作成
  3. アクション→「リソースの作成」(リソース名は、アクセスするパスになるので注意
  4. アクション→「メソッドの作成」(GETを指定し、作ったLambda関数を指定)
  5. 「メソッドリクエスト」→「URLクエリ文字列パラメータ」を追加(bucket_name)
  6. 「マッピングテンプレートの追加」(Content-Type:application/json)
  7. 「テンプレートの生成」→emptyにし、以下を入力
#set($inputRoot = $input.path('$'))
{
    "bucket_name" : "$input.params('bucket_name')"
}

 ※上記が、作成したhello関数の引数として入ってくる

$input.params(x)

パラメータ名文字列 x が指定された場合に、パス、クエリ文字列、またはヘッダー値から (この順番で検索される) メソッドリクエストパラメータの値を返します。

マッピングテンプレートで使える変数・関数
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#input-variable-reference

8.最後に、「アクション」→「APIのデプロイ」(ここで入力するステージも、アクセスするパスになるので注意

アクセスするURL

  • 「APIのデプロイ」後、Lambdaコンソールに表示されるURLを利用
  • 例えば、ステージ名が「stage」、リソース名が「myresource」、「URLクエリ文字列パラメータ」が「bucket_name」の場合、
    URL/stage/myresource?bucket_name=test191230

  • ここにアクセスすると、「test191230」というS3バケットが作成される

参考にさせて頂いた記事

AWS Lambda で Go が使えるようになったので試してみた
golang + Lambda + API GatewayでREST APIを作ってみた
AWS SDK for Go S3バケット基本操作

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

言語別int64素因数分解(試し割り法)処理時間比較

C言語、C#, Java8, Golang, Python3 で、
int64の範囲内の値を素因数分解したときの処理時間の比較してみました。

先に結果を見たい方はこちらへ。
処理時間一覧

C#, Java, Golangについては、bigintでも計算してみました。

利用した素因数分解のアルゴリズム

素因数分解のアルゴリズムについては、最も単純な試し割り法を利用しました。
2,3,5,7,13,17, ... (以下、+2, +4を交互に繰り返した値)で割れるかどうか試していきます。

処理の高速化のために、あらかじめ割れるかどうか照合する素数の表を用意しておく方法もありますが、
(63ビット程度のループ処理も10秒程度で終わったため、)今回は用意していません。

下記は、Javaでの試し割り処理の例です。

PrimeFactorization.java
private long[] trial_division(long n) {
    List<Long> prime_list = new ArrayList<>();
    long max = (long)(Math.sqrt(n)) + 1;

    // 2 で割っていく
    while (n % 2 == 0) {
        prime_list.add((long)2);
        n /= 2;
    }

    // 3 で割っていく
    while (n % 3 == 0) {
        prime_list.add((long)3);
        n /= 3;
    }

    // 5 ~ Math.sqrt(n) の数字で割っていく
    boolean flag = true;
    for (long i = 5; i < max; ) {
        while (n % i == 0) {
            prime_list.add(i);
            n /= i;
            if (n == 1)
                i = max;
        }
        if (flag)
            i += 2;
        else
            i += 4;

        flag = !flag;
    }

    if (n != 1) {
        prime_list.add(n);
    }
// (以下、省略)
}

使用言語

  • C言語 (gcc version 8.2.0(MinGW.org GCC-8.2.0-3))
  • C# (.NET Core 3.0)
  • Java8 (javac 11.0.4)
  • Golang (go version go1.12.7 windows/amd64)
  • Python3 (Python 3.7.4)

JavaとGolangについては、int64(long)型のほかに、
bigint(BigInteger)型でも同様の計算を行ってみました。

ちなみに、Python3については、整数型の上限がありませんね。

プログラムのソースは、下記に配置しています。
https://github.com/NobuyukiInoue/PrimeFactorization

計測に使用したPC

処理時間の計測は、以下のスペックもPCを使用しました。

CPU:   Intel Core-i7 8559U 2.7GHz(4.5GHz) 4コア/8スレッド
Memory: 16GB(LPDDR3 2,133MHz)
OS:    Windows 10 Professional

いわゆる、Macbook Pro 13インチ 2018モデルですね。

処理時間一覧

対象の値は、素因数分解したい値です。
("111..."が並んでいますが、2進数ではなく10進数です。)

試し割り法の場合、2,3,5,..などの小さな素数で割れた場合は、トータルのループ回数が少なくなるので、
値の大きさに比例して処理時間がかかるわけではありません。

int64の場合、64ビット程度の値でも、いまどきのPCであれば10秒以内で素因数分解ができてしまいます。

対象の値
(10進数)
C言語
long long int
C#
long
C#
BigInteger
Java
long
Java
BigInteger
Golang
int64
Golang
BigInt
Python3
int
11111111111111
(44ビット)
0.015[S] 0.004[S] 0.013[S] 0.000[S] 0.047[S] 0.003[S] 0.056[S] 0.030[S]
111111111111111
47ビット)
0.031[S] 0.008[S] 0.038[S] 0.016[S] 0.109[S] 0.007[S] 0.169[S] 0.088[S]
1111111111111111
(50ビット)
0.062[S] 0.015[S] 0.067[S] 0.031[S] 0.141[S] 0.015[S] 0.343[S] 0.176[S]
11111111111111111
(54ビット)
0.218[S] 0.257[S] 1.540[S] 0.250[S] 1.859[S] 0.271[S] 計測断念
(180秒以上)
5.021[S]
111111111111111111
(57ビット)
0.624[S] 0.002[S] 0.007[S] 0.000[S] 0.031[S] 0.001[S] 0.022[S] 0.016[S]
1111111111111111111
(60ビット)
2.156[S] 2.300[S] 15.025[S] 2.422[S] 15.688[S] 2.519[S] 計測断念
(180秒以上)
48.322[S]
6111111111111111111
(63ビット)
4.938[S] 5.396[S] 41.263[S] 5.703[S] 38.781[S] 5.937[S] 計測断念
(180秒以上
243.715[S]

(2019/12/30(Mon) 18:00更新)

感想

Golangのbigintは、ループ数が多いと、(ループ内の代入処理時にインスタンス生成が行っているため)、
とんでもなく時間がかかっています。

いくつかの言語で、57ビットの処理時間が44ビットよりも短くなっていますが、これは、

11111111111111(44ビット)の素因数[11, 239, 4649, 909091] の合計が913990に対し、
111111111111111111(57ビット)の素因数[3, 3, 7, 11, 13, 19, 37, 52579, 333667]の合計が386339であり、
ループ回数が少なく済んでいるからです。

bigintでの処理速度の比較では、C# > Java > Golang の順番といったところでしょうか。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む