「多倍長整数」を含む日記 RSS

はてなキーワード: 多倍長整数とは

2022-08-13

プログラマー生産性は人により100倍くらい差があるというけれど

 割りとマジだよねと思う出来事をふと思い出したので書いてみる。

 といっても後輩が俺の思ってもいないところでつまづいて、それに俺がカルチャーショックを受けたというだけの話。

 問題の話なんだけど、とある有名サービスJSON APIを叩いて呼び出し結果を手元のオブジェクトマッピングするというただそれだけのコードを書くというもの

 普通に考えて一日もしないで出来ると思うような代物だけど、三日以上悩んで彼はそれでも出来なかった。

 何があったかというと、そのJSON API

{ ..., "count": 10000000000000000000000000000000000000, ...}

 という感じで多倍長整数リテラルとして書かれているのを前提として受け取る仕様だった。

 JavaScriptの通常の整数と違って、JSON整数リテラル仕様上大きさの制限記載がないので、上のようなのも合法

 で、彼の使ってたプログラミング言語オブジェクト から JSONの変換ライブラリが、多倍長整数文字列("")としてシリアライズするような仕様なことがわかって、彼は行き詰まった。

 そこで何をやり始めたかというと、JSON整数がそのまま1000000000000000みたいにシリアライズされるライブラリ探し始めたんだけど、それは見つからないまま。

 というわけで「増田さん、詰まってるんですけど……」と言われて助け舟出すことになったはいものの、彼のコード見るとJSON抽象構文木クラスがそのまま使えるようだった。

 なので、

String serialiaze(Ast.JsValue value) {
    return switch(value) {
        case Ast.JsNull nullValue-> "null";
        case Ast.JsInt bigIntValue -> bigIntValue.toString();
        case Ast.JsArray arrayValue -> arrayValue.stream().map(v -> serialize(v)).collect(Collectors.joining(", ", "[", "]"));
        // 他のJSONの木についても同様に処理
        default -> throw new RuntimeException("cannot reach")
    };
}

 1時間しない内にこんな感じのコード言語Javaじゃなかったけど、だいたいこういう感じ)を書いて無事問題解決。細かいタイポとかあるかもだけど、日記では確認してないのでそれはおいといて)。

 結局、JSONの形が期待と違って、しか既存APIじゃいいのがなかったのに延々API探すことしか出来なかったのが問題解決できなかった原因だけど、このくらいのは割りとちょこちょこある。

 きっと、それから一週間放置しても問題解決できなかっただろうし、どうも同じチームの同僚も問題解決できなかったようだった。

 最近APIは叩けるけど、そこでトラブルとどうにもならなくエンジニアにちょくちょく遭遇するんだけど、やっぱりもうちょっと基礎出来てないと駄目だなと思った出来事だった。

 具体的には、再帰が相性が良いプログラムを書けるとか、APIに頼れないときはさっさと自作する頭の切り替えとかもろもろ。

 それと、情報大学出てるのなら、せめて木構造に対してはサクっと再帰関数くらい書けてほしかったなと思う出来事だった。

2010-05-10

多倍長ライブラリMPIRで複素数std::complexを扱う方法(C++)

C++プログラムで多倍長な複素数を使いたかったのでメモ

C++において多倍長整数,多倍長浮動小数点を扱うライブラリとしてGMPが有名だ.

Visual C++を使っているのなら,GMPと互換のあるMPIRが導入しやすくて良い.

以下,VC10 (Visual Studio 2010)環境での話.

このMPIRはどうもC++複素数クラスstd::complexと相性が悪いようだ.

以下のコードエラーとなってしまう.

#include <complex&gt; 
#include <iostream&gt; 
#include <iomanip&gt; 
#include <mpirxx.h&gt; 

int main()
{
	std::complex<mpf_class&gt; a(1.0, 2.0);
	std::complex<mpf_class&gt; b(0.0, 1.0);
	std::complex<mpf_class&gt; c1 = a + b;
	std::complex<mpf_class&gt; c2 = a - b;
	std::complex<mpf_class&gt; c3 = a * b;
//	std::complex<mpf_class&gt; c4 = a / b;	// error
	
	std::cout << "a  =" << a  << std::endl
	          << "b  =" << b  << std::endl
	          << "c1 =" << c1 << std::endl
	          << "c2 =" << c2 << std::endl
	          << "c3 =" << c3 << std::endl;
//	std::cout << "c4 =" << c4 << std::endl;
	return 0;
}

「operator/=」から呼び出される「_Div」内部でエラーが出る.

そこでテンプレートの特殊化をする.

#pragma once
#include <mpirxx.h&gt;
#if defined(_MSC_VER) &amp;amp;&amp;amp; (_MSC_VER == 1500)      /* VC9 (Visual Studio 2008) */
  #pragma comment(lib, "C:\\lib\\MPIR\\vc9\\mpirxx.lib")
  #pragma comment(lib, "C:\\lib\\MPIR\\vc9\\mpir.lib")
#else if defined(_MSC_VER) &amp;amp;&amp;amp; (_MSC_VER == 1600) /* VC10 (Visual Studio 2010) */
  #pragma comment(lib, "C:\\lib\\MPIR\\vc10\\mpirxx.lib")
  #pragma comment(lib, "C:\\lib\\MPIR\\vc10\\mpir.lib")
#endif

#include<complex&gt;
namespace std {
	template<&gt;
	complex<mpf_class&gt;&amp;amp; complex<mpf_class&gt;::operator/=(const complex<mpf_class&gt;&amp;amp; _Right)
	{	// divide by other complex   //this-&gt;_Div(_Right);
		mpf_class _Rightreal = (mpf_class)_Right.real();
		mpf_class _Rightimag = (mpf_class)_Right.imag();

		mpf_class bunbo = _Rightreal * _Rightreal + _Rightimag * _Rightimag;
		mpf_class re = ( this-&gt;real() * _Rightreal + this-&gt;imag() * _Rightimag ) / bunbo;
		mpf_class im = ( this-&gt;imag() * _Rightreal - this-&gt;real() * _Rightimag ) / bunbo;

		this-&gt;real(re);
		this-&gt;imag(im);
		return (*this);
	}
}

これでとりあえずは割り算もできるようになった.

計算精度については何も考えていない.

突っ込みお待ちしてます.

2009-10-28

固定少数点演算

http://d.hatena.ne.jp/shin/20091027/p1

ネットコンピュータ実数演算の誤差の話になると「固定少数なら誤差がでない」みたいなことを言う人を見かけるけど、COBOLのやつとかJavaBigDecimalは固定少数じゃないし、本当の固定少数は浮動少数と同じくやっぱり誤差が出る。

なんでこういう誤用が広まるんだろう。

大昔は、BCD多倍長整数やら、固定少数のクラスやら自分で実装したりする人も多かっただろうけど、最近言語は最初からライブラリについてるから、そのせいかなぁ。

 
ログイン ユーザー登録
ようこそ ゲスト さん