「Mery 電卓」の版間の差分
ナビゲーションに移動
検索に移動
編集の要約なし |
編集の要約なし |
||
| (同じ利用者による、間の2版が非表示) | |||
| 79行目: | 79行目: | ||
precision: 64 // 有効桁数 (デフォルトは64桁) | precision: 64 // 有効桁数 (デフォルトは64桁) | ||
}) | }) | ||
const lowerAndUpperExp = { lowerExp: -7, upperExp: 15 }; | |||
doMultiEdit(main); | doMultiEdit(main); | ||
| 99行目: | 100行目: | ||
try { | try { | ||
var exp_replaced = replaceExpression(exp); | var exp_replaced = replaceExpression(exp); | ||
var result_str = math.format(math.evaluate(exp_replaced), | var result_str = math.format(math.evaluate(exp_replaced), lowerAndUpperExp); | ||
} catch (e) { | } catch (e) { | ||
if (exp_replaced === undefined) { | if (exp_replaced === undefined) { | ||
alert("エラー発生" + "\n------\n" + e | alert("エラー発生" + "\n------\n" + e) | ||
} else { | } else { | ||
alert(" | alert("整形後の数式で計算エラーが発生" + "\n------\n" + e + "\n元の数式: " + exp + "\n整形後の数式: " + exp_replaced) | ||
} | } | ||
return; | return; | ||
| 141行目: | 142行目: | ||
const inputExp = exp.replace(/((?!;)\n)/mg, "; ").replace(/;\s*;/g, ";").replace(/ /g, " ").replace(/;\s*$/, "").trim(); | const inputExp = exp.replace(/((?!;)\n)/mg, "; ").replace(/;\s*;/g, ";").replace(/ /g, " ").replace(/;\s*$/, "").trim(); | ||
if (exp.slice(-1) === "\n") { | if (exp.slice(-1) === "\n") { | ||
sel.Text = inputExp + ' = ' + result_str + '\n'; | sel.Text = inputExp + '\n= ' + result_str + '\n'; | ||
} else { | } else { | ||
sel.Text = '\n' + inputExp + ' = ' + result_str + '\n'; | sel.Text = '\n' + inputExp + '\n= ' + result_str + '\n'; | ||
} | } | ||
sel.CharLeft(); | sel.CharLeft(); | ||
| 158行目: | 159行目: | ||
*/ | */ | ||
function replaceExpression(exp) { | function replaceExpression(exp) { | ||
const exp_replaced = | // コメント扱いの記載を削除 | ||
let exp_replaced = exp.replace(/`[^`]*`/g, " ") | |||
// 他の言語で対応する演算子などはあらかじめエラーにする | |||
const invalidOperators = ["**", "//"]; | |||
invalidOperators.forEach(operator => { | |||
if (exp.includes(operator)) { | |||
throw new Error(`「${operator}」はサポートされていません`); | |||
} | |||
}); | |||
exp_replaced = exp_replaced.trim() | |||
// 先頭の = を削除 | // 先頭の = を削除 | ||
.replace(/^= /, "") | .replace(/^= /, "") | ||
| 175行目: | 187行目: | ||
// 指数形式を退避 | // 指数形式を退避 | ||
.replace(/([0-9]+(?:\.[0-9]+)?[eE][+\-]?[0-9]+)/g, " %%%$1%%% ") | .replace(/([0-9]+(?:\.[0-9]+)?[eE][+\-]?[0-9]+)/g, " %%%$1%%% ") | ||
// | // 変数形式を退避してからドル記号削除 | ||
.replace(/(\$[a-zA-Z][a-zA-Z0-9]*)/g, " %%%$1%%% ") | .replace(/(\$[a-zA-Z][a-zA-Z0-9]*)/g, " %%%$1%%% ") | ||
.replace(/\$/g, "") | |||
.replace(/\ | // 空の括弧を削除 | ||
// | .replace(/\(\s*\)|\[\s*\]|\{\s*\}/g, " ") | ||
.replace(/ | |||
// 関数形式になっていない文字列を削除 | // 関数形式になっていない文字列を削除 | ||
.replace(/( [a-zA-Z][a-zA-Z0-9]*)(%%% |\()?/g, (match, p1, p2) => { | .replace(/([ ,+\-*\/%^&~|<>?])([a-zA-Z][a-zA-Z0-9]*)(%%% |\()?/g, (match, p1, p2, p3) => { | ||
return | return p3 ? p1 + p2 + p3 : p1 + " "; | ||
}) | }) | ||
// `/hour` などの文字列があるとスラッシュだけ残るためスラッシュを削除 | |||
.replace(/\/\s*([,+\-*\/%^&~|<>?/)\];\n]|$)/g, "$1") | |||
// 退避文字を復元 | // 退避文字を復元 | ||
.replace(/ %%%\$([a-zA-Z][a-zA-Z0-9]*)%%% /g, " $1 ") | .replace(/ %%%\$([a-zA-Z][a-zA-Z0-9]*)%%% /g, " $1 ") | ||
| 196行目: | 209行目: | ||
[https://github.com/josdejong/mathjs math.js] | [https://github.com/josdejong/mathjs math.js] | ||
== 更新履歴 == | |||
* 2025-10-19 公開 | |||
* 2025-10-25 対象テキストを数式に整形する処理を調整 | |||
2025年10月25日 (土) 14:26時点における最新版
概要[編集]
「Mery 電卓」は、Meryエディタ上で数式を計算するためのマクロです。標準的な数学関数をサポートしており、カーソル位置の行または選択したテキストを数式として解釈し、結果を表示します。計算結果は自動的にクリップボードにコピーされ、カンマ区切りの数値として表示されます。
本マクロをショートカットキーに設定し、いつでも起動できるようにしておくと日常シーンで何かと便利です。作者は「Ctrl + Alt + Enter」キーに割り当てて利用しています。
注意事項[編集]
- Mery Ver 3.7.19 で動作確認しています。
使い方[編集]
0. 事前準備
- 本マクロでは計算エンジンライブラリの「math.js」をインポートして利用しています。当該ライブラリをマクロフォルダーに配置します。
- ダウンロード先: https://unpkg.com/mathjs@15.0.0/lib/browser/math.js
- 保存ファイル名: math_v15.0.0.js
1. 行全体を計算する場合:
- 計算したい数式が書かれた行にカーソルを置きます。
- マクロを実行すると、次の行に「= 計算結果」が表示されます。
- 既に結果行がある場合は、その行が更新されます。
2. 選択範囲を計算する場合:
- 計算したい数式部分を選択します。
- マクロを実行すると、選択範囲の後ろに「計算式 = 計算結果」が挿入されます。
3. サポートされている演算子:
- 四則演算(+, -, *, /)
- べき乗(^)
- 剰余(%, mod)
- 比較演算子(<, >, <=, >=, ==, !=)
- 論理演算子(and, or, not)
4. サポートされている関数:
- 三角関数(sin, cos, tan, asin, acos, atan)
- 双曲線関数(sinh, cosh, tanh, asinh, acosh, atanh)
- 対数関数(log, log10, log2, log1p)
- その他の数学関数(sqrt, cbrt, abs, ceil, floor, round, trunc など)
- その他の利用可能な関数は math.js の公式リファレンス https://mathjs.org/docs/reference/functions.html を参照
5. 特別な機能:
- カンマ区切り表示: 計算結果は読みやすいようにカンマ区切りで表示されます。変数「COMMA」を調整することで制御できます。
- 自動コピー: 計算結果は自動的にクリップボードにコピーされます。変数「COPY」を調整することで制御できます。
- 計算結果の再利用: 行頭の「= 」は計算実行時に無視されるため、計算結果をスムーズに次の式として利用できます。
- 変数の利用: 複数行、または「;」で区切ることで、変数を使った数式が利用できます。変数形式は「$[a-zA-Z][a-zA-Z0-9]*」に対応しています。例えば「$a = 2; $a * 3」として実行すると、結果は「6」と出力されます。
- メモ書きから計算: 数字や関数以外の文字はできるだけ除外した上で計算をします。例えば「月100円 * 12ヶ月」のようなメモ書きに対して実行すると「1,200」と出力されます。また「` (バッククォート)」で囲んだ文字は確実に無視されるため、計算メモ用として使うことができます (使用例: 『1500円 `金額未定のため仮置き`』)。
ソースコード[編集]
#title = "Mery 電卓"
#language = "v8"
#include "Common.js"
#include "math_v15.0.0.js"
Redraw = false;
BeginUndoGroup();
// 以下のようなCDNから math.js 本体を入手し、マクロフォルダに配置して利用している。
// https://unpkg.com/mathjs@15.0.0/lib/browser/math.js
// 以下の math.js 関数リファレンス掲載の関数を式内で利用することができる。
// https://mathjs.org/docs/reference/functions.html
// 結果をクリップボードにコピー
var COPY = true;
// 出力結果をカンマ区切りにする
var COMMA = true;
var sel = document.selection;
// math.js 初期設定
math.config({
number: 'BigNumber', // デフォルトの数値型を BigNumber に設定
precision: 64 // 有効桁数 (デフォルトは64桁)
})
const lowerAndUpperExp = { lowerExp: -7, upperExp: 15 };
doMultiEdit(main);
function main() {
var isEmpty = sel.IsEmpty;
var activePointY = sel.GetActivePointY(mePosLogical);
if (isEmpty) {
var exp = document.GetLine(activePointY);
} else {
var exp = sel.Text;
}
// 空白行の場合は何もしない
if (exp.match(/^\s*$/)) {
return;
}
// 計算実行
try {
var exp_replaced = replaceExpression(exp);
var result_str = math.format(math.evaluate(exp_replaced), lowerAndUpperExp);
} catch (e) {
if (exp_replaced === undefined) {
alert("エラー発生" + "\n------\n" + e)
} else {
alert("整形後の数式で計算エラーが発生" + "\n------\n" + e + "\n元の数式: " + exp + "\n整形後の数式: " + exp_replaced)
}
return;
}
// 小数点以上のみカンマ区切り
if (COMMA && result_str.match(/^[0-9]+(\.[0-9]+)?$/)) {
var result_parts = result_str.split(".");
result_parts[0] = result_parts[0].replace(/(\d)(?=(\d{3})+$)/g, "$1,");
if (result_parts.length > 1) {
result_str = result_parts.join(".");
} else {
result_str = result_parts[0];
}
}
// 計算行が = 始まりの場合、= を削除する
if (isEmpty && exp.match(/^= /)) {
sel.SetActivePoint(mePosLogical, 1, activePointY, false);
sel.EndOfLine(true, mePosLogical);
sel.Text = sel.Text.replace(/^= /, "");
}
// 既存の計算結果を上書きするか判定
var pattern = /^=\s*(-?[0-9.,]|true|false|\[[0-9., \[\]]+\])*\s*$/;
var nextLine = document.GetLine(activePointY + 1);
if (isEmpty && nextLine.match(pattern)) {
sel.SetActivePoint(mePosLogical, 1, activePointY + 1, false);
sel.EndOfLine(true, mePosLogical);
sel.Text = '= ' + result_str
} else if (isEmpty) {
sel.LineOpen();
sel.Text = '= ' + result_str
} else {
sel.CharRight();
const inputExp = exp.replace(/((?!;)\n)/mg, "; ").replace(/;\s*;/g, ";").replace(/ /g, " ").replace(/;\s*$/, "").trim();
if (exp.slice(-1) === "\n") {
sel.Text = inputExp + '\n= ' + result_str + '\n';
} else {
sel.Text = '\n' + inputExp + '\n= ' + result_str + '\n';
}
sel.CharLeft();
}
if (COPY) {
ClipboardData.SetData(result_str);
Status = "計算結果 " + result_str + " をコピーしました"
}
}
/**
* 数式を置換する
*/
function replaceExpression(exp) {
// コメント扱いの記載を削除
let exp_replaced = exp.replace(/`[^`]*`/g, " ")
// 他の言語で対応する演算子などはあらかじめエラーにする
const invalidOperators = ["**", "//"];
invalidOperators.forEach(operator => {
if (exp.includes(operator)) {
throw new Error(`「${operator}」はサポートされていません`);
}
});
exp_replaced = exp_replaced.trim()
// 先頭の = を削除
.replace(/^= /, "")
// 改行を ; に置換
.replace(/(?<!;)\n/mg, ";")
// 非ASCII文字を削除
.replace(/[^\x20-\x7e]/g, " ")
// 全角スペースを半角スペースに変換
.replace(/ /g, " ")
// 数字内のカンマを取り除く。[1,2] [1, 2] {a: 1, b: 2} mod(1, 2) のような形式では削除しない
.replace(/(\d),(?=\d{3})/g, '$1')
// 予約語を退避
.replace(/(?:^|\s)(PI|true|false)(?:$|\s)/g, " %%%$1%%% ")
.replace(/([0-9]+|\$[a-zA-Z0-9]+) (mod|and|or|xor) ([0-9]+|\$[a-zA-Z0-9]+)/g, "$1 %%%$2%%% $3")
.replace(/not ([0-9]+|\$[a-zA-Z0-9]+)/g, " %%%$1%%% $2")
// 指数形式を退避
.replace(/([0-9]+(?:\.[0-9]+)?[eE][+\-]?[0-9]+)/g, " %%%$1%%% ")
// 変数形式を退避してからドル記号削除
.replace(/(\$[a-zA-Z][a-zA-Z0-9]*)/g, " %%%$1%%% ")
.replace(/\$/g, "")
// 空の括弧を削除
.replace(/\(\s*\)|\[\s*\]|\{\s*\}/g, " ")
// 関数形式になっていない文字列を削除
.replace(/([ ,+\-*\/%^&~|<>?])([a-zA-Z][a-zA-Z0-9]*)(%%% |\()?/g, (match, p1, p2, p3) => {
return p3 ? p1 + p2 + p3 : p1 + " ";
})
// `/hour` などの文字列があるとスラッシュだけ残るためスラッシュを削除
.replace(/\/\s*([,+\-*\/%^&~|<>?/)\];\n]|$)/g, "$1")
// 退避文字を復元
.replace(/ %%%\$([a-zA-Z][a-zA-Z0-9]*)%%% /g, " $1 ")
.replace(/ %%%([^%]+)%%% /g, " $1 ")
return exp_replaced;
}
サードパーティライブラリ[編集]
更新履歴[編集]
- 2025-10-19 公開
- 2025-10-25 対象テキストを数式に整形する処理を調整
スポンサーリンク