GCD

引数に指定した配列の最大公約数(Greatest Common Divisor)を求めます。ユークリッド互除法で最大公約数を求めています。

構文
  1. Double = GCD( arr )
引数
arr必須
最大公約数を求める数値を格納した配列
戻り値
最大公約数

プログラム

UWSC
//////////////////////////////////////////////////
// 【引数】
//   arr : 最大公約数を求める数値を格納した配列 
// 【戻値】
//   最大公約数 
//////////////////////////////////////////////////
FUNCTION GCD(arr[])
	DIM c = LENGTH(arr)
	DIM rem = arr[c-1] MOD arr[c-2]
	IFB rem = 0 THEN
		IFB LENGTH(arr) = 2 THEN
			RESULT = arr[c-2]
			EXIT
		ENDIF
		RESIZE(arr, c-2)
		RESULT = GCD(arr)
		EXIT
	ENDIF
	arr[c-1] = arr[c-2]
	arr[c-2] = rem
	RESULT = GCD(arr)
FEND

解説

  1. 2行目
    UWSC
    	DIM c = LENGTH(arr)
    arr の要素数を変数 c に代入。
  2. 3行目
    UWSC
    	DIM rem = arr[c-1] MOD arr[c-2]
    arrc -1番目を c -2番目で割った余りを rem に代入。
  3. 4,12行目
    UWSC
    	IFB rem = 0 THEN
    		…
    	ENDIF
    rem の値が0ならば5行目>>>
  4. 5-11行目
    UWSC
    		IFB LENGTH(arr) = 2 THEN
    			RESULT = arr[c-2]
    			EXIT
    		ENDIF
    		RESIZE(arr, c-2)
    		RESULT = GCD(arr)
    		EXIT
    arr の要素数が2ならば、 arrc -2番目を返して終了。
    配列の要素数を c -2にする。GCDを再帰呼び出し。
  5. 13-15行目
    UWSC
    	arr[c-1] = arr[c-2]
    	arr[c-2] = rem
    	RESULT = GCD(arr)

プログラム実行例

最大公約数を求めます

12と18の最大公約数を求めます。

UWSC
DIM arr[] = 12, 18
PRINT GCD(arr)

//////////////////////////////////////////////////
// 【引数】
//   arr : 最大公約数を求める数値を格納した配列 
// 【戻値】
//   最大公約数 
//////////////////////////////////////////////////
FUNCTION GCD(arr[])
	DIM c = LENGTH(arr)
	DIM rem = arr[c-1] MOD arr[c-2]
	IFB rem = 0 THEN
		IFB LENGTH(arr) = 2 THEN
			RESULT = arr[c-2]
			EXIT
		ENDIF
		RESIZE(arr, c-2)
		RESULT = GCD(arr)
		EXIT
	ENDIF
	arr[c-1] = arr[c-2]
	arr[c-2] = rem
	RESULT = GCD(arr)
FEND
    (2)
結果
プレーンテキスト
6
解説
  1. 1行目
    UWSC
    DIM arr[] = 12, 18
    最大公約数を求める数値を配列に格納します。
  2. 2行目
    UWSC
    PRINT GCD(arr)
    GCD関数で最大公約数を求めて出力します。

二次方程式を解く

UWSC
DIM frac[2]

DIM coeff = SPLIT(INPUT("係数を入力してください。「ax^2+bx+c=0」の「a,b,c」を入力。"), ",")

DIM a = coeff[0]
DIM b = coeff[1]
DIM c = coeff[2]

// 判別式
DIM D = EVAL("POWER(b, 2) - 4 * a * c")

DIM ans[-1]
DIM digit = -3

SELECT TRUE
	CASE D > 0
		IFB b = 0 THEN
			DIM root = simplifySqrt(D)
			frac[0] = root[0]
			frac[1] = EVAL("2 * a")
			num = GCD(frac)
			IFB frac[1] = ABS(num) THEN
				res = frac[0] / ABS(num)
			ELSE
				res = frac[0] + "/" + frac[1]
			ENDIF
			arrayPush(ans, (IIF(frac[0] / num <> 1, frac[0] / num, "") + IIF(root[1] <> 1, "√(" + root[1] + ")", "")))
			arrayPush(ans, (IIF(frac[0] / num <> 1, -frac[0] / num, "") + IIF(root[1] <> 1, "√(" + root[1] + ")", "")))
		ELSE
			// 約分する
			frac[0] = EVAL("-b")
			frac[1] = EVAL("2 * a")
			num = GCD(frac)
			IFB frac[1] = ABS(num) THEN
				res = frac[0] / ABS(num)
			ELSE
				res = frac[0] + "/" + frac[1]
			ENDIF
			// ルートの中から整数を外に出す
			root = simplifySqrt(D)
			frac[0] = root[0]
			num = GCD(frac)
			IFB frac[1] = num THEN
				arrayPush(ans, res + "+" + (IIF(frac[0] / num <> 1, frac[0] / num, "") + "√(" + root[1] + ")"))
				arrayPush(ans, res + "-" + (IIF(frac[0] / num <> 1, frac[0] / num, "") + "√(" + root[1] + ")"))
			ELSE
				arrayPush(ans, res + "+(" + (IIF(frac[0] / num <> 1, frac[0] / num, "") + "√(" + root[1] + "))/" + (frac[1] / num)))
				arrayPush(ans, res + "-(" + (IIF(frac[0] / num <> 1, frac[0] / num, "") + "√(" + root[1] + "))/" + (frac[1] / num)))
			ENDIF
		ENDIF
	CASE D = 0
		arrayPush(ans, ROUND(EVAL("-b/(2*a)"), digit))
	CASE D < 0
		IFB b = 0 THEN
			root = simplifySqrt(D)
			frac[0] = root[0]
			frac[1] = EVAL("2 * a")
			num = GCD(frac)
			IFB frac[1] = ABS(num) THEN
				res = frac[0] / ABS(num)
			ELSE
				res = frac[0] + "/" + frac[1]
			ENDIF
			arrayPush(ans, (IIF(frac[0] / num <> 1, frac[0] / num, "") + IIF(root[1] <> 1, "√(" + root[1] + ")", "")))
			arrayPush(ans, (IIF(frac[0] / num <> 1, -frac[0] / num, "") + IIF(root[1] <> 1, "√(" + root[1] + ")", "")))
		ELSE
			frac[0] = EVAL("-b")
			frac[1] = EVAL("2 * a")
			num = GCD(frac)
			IFB frac[1] = ABS(num) THEN
				res = frac[0] / ABS(num)
			ELSE
				res = IIF(frac[0] * frac[1] < 0, "-", "") + ABS(frac[0] / num) + "/" + ABS(frac[1] / num)
			ENDIF
			// ルートの中から整数を外に出す
			root = simplifySqrt(ABS(D))
			frac[0] = root[0]
			num = GCD(frac)
			IFB frac[1] = num THEN
				arrayPush(ans, res + "+" + (IIF(frac[0] / num <> 1, frac[0] / num, "") + "√(" + root[1] + ")i"))
				arrayPush(ans, res + "-" + (IIF(frac[0] / num <> 1, frac[0] / num, "") + "√(" + root[1] + ")i"))
			ELSE
				arrayPush(ans, res + "+(" + (IIF(frac[0] / num <> 1, frac[0] / num, "") + "√(" + root[1] + ")i)/" + (frac[1] / num)))
				arrayPush(ans, res + "-(" + (IIF(frac[0] / num <> 1, frac[0] / num, "") + "√(" + root[1] + ")i)/" + (frac[1] / num)))
			ENDIF
		ENDIF
SELEND

PRINT REPLACE(IIF(a <> 1, a, "") +"x^2+" + b + "x+" + c, "+-", "-")
PRINT "-----"

FOR item IN ans
	PRINT item
NEXT

//////////////////////////////////////////////////
// 【引数】
//   num : ルートの中
// 【戻値】
//   整数を外に出す
//////////////////////////////////////////////////
FUNCTION simplifySqrt(num)
	HASHTBL root
	
	DIM arr = primeFactorization(num)
	DIM a = 1, b = 1
	
	FOR item IN arr
		root[item] = root[item] + 1
	NEXT
	
	FOR n = 0 TO LENGTH(root) - 1
		IF INT(root[n, HASH_VAL] /  2) <> 0 THEN a = a * POWER(root[n, HASH_KEY], INT(root[n, HASH_VAL] /  2))
		IF (root[n, HASH_KEY] * (root[n, HASH_VAL] MOD 2)) <> 0 THEN b = b * (root[n, HASH_KEY] * (root[n, HASH_VAL] MOD 2))
	NEXT
	
	DIM res[1] = a, b
	
	RESULT = SLICE(res)
FEND

//////////////////////////////////////////////////
// 【引数】
//   array : 要素を追加する配列(参照引数) 
//   str : 追加する要素 
// 【戻値】
//   処理後の配列の中の要素の数 
//////////////////////////////////////////////////
FUNCTION arrayPush(var arr[], str)
	DIM res = RESIZE(arr, UBound(arr) + 1)
	arr[res] = str
	RESULT = res + 1
FEND

//////////////////////////////////////////////////
// 【引数】
//   arr : 最大公約数を求める数値を格納した配列 
// 【戻値】
//   最大公約数 
//////////////////////////////////////////////////
FUNCTION GCD(arr[])
	DIM c = LENGTH(arr)
	DIM rem = arr[c-1] MOD arr[c-2]
	IFB rem = 0 THEN
		IFB LENGTH(arr) = 2 THEN
			RESULT = arr[c-2]
			EXIT
		ENDIF
		RESIZE(arr, c-2)
		RESULT = GCD(arr)
		EXIT
	ENDIF
	arr[c-1] = arr[c-2]
	arr[c-2] = rem
	RESULT = GCD(arr)
FEND

//////////////////////////////////////////////////
// 【引数】
//   expr : 評価する式 
//   truepart : 評価した式がTrueのときに返す値 
//   falsepart : 評価した式がFalseのときに返す値 
// 【戻値】
//   truepart : 評価した式がTrueのとき、falsepart : 評価した式がFalseのとき 
//////////////////////////////////////////////////
FUNCTION IIF(expr, truepart, falsepart)
	IFB EVAL(expr) THEN
		RESULT = truepart
	ELSE
		RESULT = falsepart
	ENDIF
FEND

//////////////////////////////////////////////////
// 【引数】
//   num : 素因数分解する数値 
// 【戻値】
//   素因数分解した数値を格納した配列 
//////////////////////////////////////////////////
FUNCTION primeFactorization(num)
	DIM arr[-1]
	// 偶数なら2で割り続ける
	WHILE num MOD 2 = 0
		arrayPush(arr, 2)
		num = num / 2
	WEND
	FOR n = 3 TO num
		WHILE num MOD n = 0
			arrayPush(arr, n)
			num = num / n
		WEND
	NEXT
	RESULT = SLICE(arr)
FEND

//////////////////////////////////////////////////
// 【引数】
//   array : 上限値を求める配列 
// 【戻値】
//   配列の上限値 
//////////////////////////////////////////////////
FUNCTION UBound(array[])
	RESULT = RESIZE(array)
FEND
    (3) (3) (10,20,31,32,52,57,67,68) (21,33,42,58,69,78) (22,23,34,35,59,60,70,71,73,76) (27,28,44,45,47,48,52,64,65,80,81,83,84) (27.28,44,45,47,48,64,65,73,80,81,83,84,89) (52) (89)
結果
プレーンテキスト
4x^2+5x+3
-----
-5/8+(√(23)i)/8
-5/8-(√(23)i)/8

関連記事

fact (自作関数)
引数に指定した数値の 階乗 を求めます。
factDouble (自作関数)
引数に指定した数値の 二重階乗 を求めます。
ABS (スクリプト関数)
引数の絶対値(\(|x|\))を返します。
ARCCOS (スクリプト関数)
引数の 逆余弦 を求めます。
CEIL (スクリプト関数)
正の値へ切り上げた数値を返します。
LN (スクリプト関数)
自然対数(\(\log_e{x}\))を求める。
LOGN (スクリプト関数)
Baseを底とするXの対数(\(\log_{Base}{x}\))を求める。
ZCUT (スクリプト関数)
マイナス値は0にして返します。
isEven (自作関数)
偶数かどうかを調べます。
isOdd (自作関数)
奇数かどうか調べます。
radToDeg (自作関数)
弧度法 から 度数法 に変換します。
ARCSIN (スクリプト関数)
引数の 逆正弦 を求めます。
EXP (スクリプト関数)
自然指数関数(\(y=e^{x}\))を求める。
degToRad (自作関数)
度数法 から 弧度法 に変換します。
LCM (自作関数)
最小公倍数 を求めます。
binToDec (自作関数)
2進数を10進数に変換します。負数・小数の値にも対応しています。
binToHex (自作関数)
2進数を16進数に変換します。負数・小数の値にも対応しています。
ARCTAN (スクリプト関数)
引数の 逆正接 を求めます。
INT (スクリプト関数)
小数点以下を切り落とした数値を返します。
POWER (スクリプト関数)
数値のべき乗(\(\small{Base}^{Exponent}\))を求めます。
hexToBin (自作関数)
16進数を2進数に変換します。負数・小数の値にも対応しています。
isPrime (自作関数)
指定した数値が 素数 かどうかを調べます。
normalizeAngle (自作関数)
度単位の角度を0~360度に正規化します。
divisors (自作関数)
引数に指定した数値の約数のリストを返します。
RANDOM (スクリプト関数)
ランダムな値を返します。
ROUND (スクリプト関数)
指定した位置で偶数丸めした値を返します。
SQRT (スクリプト関数)
平方根(\(\sqrt{x}\))を求める。
digitSum (自作関数)
数値の各桁の和を返す
Collatz (自作関数)
コラッツ数列 を求め結果を配列で返します。
Kaprekar (自作関数)
カプレカ数 を求め結果を配列で返します。
deleteEmptyFolders (自作関数)
指定したフォルダより下層にある空フォルダを削除します。
hexToDec (自作関数)
16進数を10進数に変換します。負数・小数の値にも対応しています。
decToHex (自作関数)
10進数を16進数に変換します。負数・小数の値にも対応しています。
decToBin (自作関数)
10進数を2進数に変換します。負数・小数の値にも対応しています。
ARABIC (自作関数)
ローマ数字 を アラビア数字 に変換します。
ROMAN (自作関数)
アラビア数字 を ローマ数字 に変換します。
timeValue (自作関数)
指定した時間の シリアル値 を求める。