0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【S-Calc】C#.NET × xFunc で複素数対応: log(-5)を解ける関数電卓を作るまで

Posted at

普段はWindows向け関数電卓ソフト「S-Calc」を個人開発しています。
今回、負の値を底に持つ対数log(-5)が計算できない問題に直面しました。
原因は内部で利用している数式エンジンxFuncが負の値の対数をサポートしていないためです。

この記事では、どのようにして「負の値を含む対数」をサポートしたか、
そしてC#.NETのSystem.Numerics.Complex.Logを活用した実装方法について簡単にまとめます。

まず、C#.NETのMath.Log10は引数に負の数を渡すとNaNを返します。
image.png
また、xFuncは実数ドメインのみの対応なので、複素数ドメインの対数が計算できません。

これではS-Calcの関数電卓としての有用性が失われてしまうと考え、以下の解決策を考えました。

解決策

  • 正規表現でlog(base, value)を先に拾う
const string pattern = @"(?i)\blog\((?<base>[^,]+),(?<val>[^\)]+)\)";
var match = Regex.Match(expr, pattern);
if (match.Success)
{
    var b = EvalAsComplex(match.Groups["base"].Value);
    var v = EvalAsComplex(match.Groups["val"].Value);
    var result = Complex.Log(v, b.Real);
    expr = expr.Replace(match.Value, ToLiteral(result));
}

※実際に実装したソースとは異なりますが、このような形です

  • C#.NETのComplex.Log(value, base)で拾った対数関数を計算する
  • 計算結果を複素数である"a+bi"のカタチに整形して元の式に差し替え、xFunc.Mathに渡す

これらを実装する際、以下のような工夫をしました。

  • 入れ子のlog(log(...))にも対応できるよう再帰的に処理
  • gamma()など他の関数が入っていても再計算できるようにした

その結果、以下のようなケースのテストを網羅し実装を終えました。

  • log(10,-5) → 0.69897 + 1.36437i
    image.png
  • log(e,-1) → 3.1419i
    image.png
  • log(2,√(-9)) → 1.585 + 2.2662i
    image.png
    ※ Shiftボタンを押下することで関数ボタンの切り替えが可能です

結び

複素数対応は「ニッチ」ではありますが、
理系ユーザにとっては「普通の電卓では絶対に出せない解」を与えらえる差別化ポイントになりました。

実際に動作する関数電卓「S-Calc」はMicrosoft Storeで公開しています。
https://apps.microsoft.com/detail/9n2gm51phq7p?hl=ja-jp&gl=JP

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?