ab.com コミュニティ

ActiveBasicを通したコミュニケーション
現在時刻 - 2018年7月19日(木) 06:42

All times are UTC+09:00




新しいトピックを投稿する  トピックへ返信する  [ 7 件の記事 ] 

この関数は役に立ったか
全然。まったく。
ちょっとだけ。すこし。
まぁまぁ。普通。
けっこう。かなり。
とても。ものすごく。
1 個のオプションを選択できます

投票結果を見る
作成者 メッセージ
投稿記事Posted: 2006年4月05日(水) 06:29 
オフライン

登録日時: 2005年7月25日(月) 13:27
記事: 893
住所: 埼玉県東松山市
関数のソースコード

[hide]
コード:
Function StrForQWord$(qwd As QWord) As String
	Dim buffer[32] As Byte
	Dim i As Long
	Dim a As QWord
	Dim s=48 As Byte
	Dim buffer2[32] As Byte
	Dim I As Long
	Dim x As QWord
	Dim y As QWord
	i = 0
	x = 10
	y = 1
	debug
	Do
		a = qwd Mod x
		buffer[i] = Waru_QWord(a,y) + s As Byte
		qwd = qwd - a
		x = x * 10
		y = y * 10
		i = i + 1
	Loop Until qwd = 0
	buffer2[i] = 0
	For I=1 To i
		buffer2(I-1)=buffer(i-I)
	Next I
	StrForQWord$ = MakeStr(buffer2)
End Function

Function Waru_QWord(A As QWord,B As QWord) As Byte
	Dim C As QWord
	Dim I As Byte
	Do
		C=A
		A=A-B
		If A>C then Exit Do
		I=I+1
	Loop
	Waru_QWord=I
End Function

Function ValForQWordString(A$ As String) As QWord
	ValForQWordString=ValForQWord(StrPtr(A$))
End Function

Function ValForQWord(pA As BytePtr) As QWord
	Dim I As Long
	Dim buffer(32) As Byte
	Dim A$ As String
	Dim x As QWord
	A$=MakeStr(pA)
	For I=0 To Len(A$)-1
		buffer(I)=A$(I)-48
	Next I
	x=1
	For I=Len(A$)-1 To 0 Step -1
		If buffer(I)>10 then Exit For
		ValForQWord = ValForQWord + Kakeru_QWord(buffer(I),x)
		x = x * 10
	Next I
End Function

Function Kakeru_QWord(A As Byte,B As QWord) As QWord
	Dim C As QWord
	Dim I As Long
	C = 0
	If A>1 then
		For I=1 To A
			C = C + B
		Next I
	Else
		C = B
	End If
	Kakeru_QWord = C
End Function

Sub InputForQWord(PrintString As String,fQuestion As Long,ByRef Inp As QWord)

	Dim A$ As String

	If fQuestion then
		Print PrintString+"?";
	Else
		Print PrintString;
	End If
	
	Input A$
	Inp=ValForQWordString(A$)
End Sub

Sub PrintForQWord(PrintQWord As QWord,fReturn As Long)
	Dim A$ As String
	A$=StrForQWord$(PrintQWord)
	If fReturn then
		Print A$
	Else
		Print A$;
	End If
End Sub

Function StrForInt64$(it64 As Int64) As String
	Dim buffer[32] As Byte
	Dim i As Long
	Dim a As QWord
	Dim s=48 As Byte
	Dim buffer2[32] As Byte
	Dim I As Long
	Dim x As QWord
	Dim y As QWord
	Dim flag=0 As Long
	If it64<0 then
		flag=1
		it64 = -1 * it64
	End If
	i = 0
	x = 10
	y = 1
	Do
		a = it64 Mod x
		buffer[i] = Waru_Int64(a,y) + s
		it64 = it64 - a
		x = x * 10
		y = y * 10
		i = i + 1
	Loop Until it64 = 0
	buffer2[i] = 0
	For I=1 To i
		buffer2(I-1)=buffer(i-I)
	Next I
	StrForInt64$ = MakeStr(buffer2)
	If flag=1 then
		StrForInt64$="-"+StrForInt64$
	End If
End Function

Function Waru_Int64(A As Int64,B As Int64) As Byte
	Dim I As Byte
	Do
		A=A-B
		If 0>A then Exit Do
		I=I+1
	Loop
	Waru_Int64=I
End Function

Function ValForInt64String(A$ As String) As Int64
	ValForInt64String=ValForInt64(StrPtr(A$))
End Function

Function ValForInt64(pA As BytePtr) As Int64
	Dim I As Long
	Dim buffer(32) As Byte
	Dim A$ As String
	Dim x As Int64
	A$=MakeStr(pA)
	For I=0 To Len(A$)-1
		buffer(I)=A$(I)-48
	Next I
	x=1
	For I=Len(A$)-1 To 0 Step -1
		If buffer(I)>10 then Exit For
		ValForInt64 = ValForInt64 + Kakeru_Int64(buffer(I),x)
		x = x * 10
	Next I
End Function

Function Kakeru_Int64(A As Byte,B As Int64) As Int64
	Dim C As QWord
	Dim I As Long
	C = 0
	If A>1 then
		For I=1 To A
			C = C + B
		Next I
	Else
		C = B
	End If
	Kakeru_Int64 = C
End Function

Sub InputForInt64(PrintString As String,fQuestion As Long,ByRef Inp As Int64)

	Dim A$ As String

	If fQuestion then
		Print PrintString+"?";
	Else
		Print PrintString;
	End If
	
	Input A$
	Inp=ValForInt64String(A$)
End Sub

Sub PrintForInt64(PrintInt64 As Int64,fReturn As Long)
	Dim A$ As String
	A$=StrForInt64$(PrintInt64)
	If fReturn then
		Print A$
	Else
		Print A$;
	End If
End Sub
[/hide]

各関数の説明
[hide=ここをクリックすると各関数の説明が表示されます。]
StrForQWord$(qwd As QWord) As String
第一パラメータ:String型にするためのQWord型変数を入れてください。
概要:指定した数値を文字列に変換します。

ValForQWordString(A$ As String) As QWord
第一パラメータ:QWord型にするためのString型変数を入れてください。
概要:指定した文字列を数値に変換します。

ValForQWord(pA As BytePtr) As QWord
第一パラメータ:QWord型にするための文字列ポインタを入れてください。
概要:指定した文字列ポインタにある文字列を数値に変換します。

InputForQWord(PrintString As String,fQuestion As Long,ByRef Inp As QWord)

第一パラメータ:質問時に表示する文字列を入れてください。
第二パラメータ:疑問符をつける場合はTRUEを、つけない場合はFALSEを入れてください。
第三パラメータ:返り値を格納するためのQWord型変数を入れてください。
注意:Promptディレクティブが読み込まれている必要があります。
概要:ユーザーからのデータ入力(数値)を受け付けます。

PrintForQWord(PrintQWord As QWord,fReturn As Long)

第一パラメータ:表示するQWord型変数を入れてください。
第二パラメータ:リターンする場合はTRUEを、しない場合はFALSEを入れてください。
注意:Promptディレクティブが読み込まれている必要があります。
概要:QWord型変数を表示します。


StrForInt64$(it64 As Int64) As String
第一パラメータ:Int64型にするためのQWord型変数を入れてください。
概要:指定した数値を文字列に変換します。

ValForInt64String(A$ As String) As Int64
第一パラメータ:Int64型にするためのString型変数を入れてください。
概要:指定した文字列を数値に変換します。

ValForInt64(pA As BytePtr) As Int64
第一パラメータ:Int64型にするための文字列ポインタを入れてください。
概要:指定した文字列ポインタにある文字列を数値に変換します。

InputForInt64(PrintString As String,fQuestion As Long,ByRef Inp As Int64)

第一パラメータ:質問時に表示する文字列を入れてください。
第二パラメータ:疑問符をつける場合はTRUEを、つけない場合はFALSEを入れてください。
第三パラメータ:返り値を格納するためのInt64型変数を入れてください。
注意:Promptディレクティブが読み込まれている必要があります。
概要:ユーザーからのデータ入力(数値)を受け付けます。

PrintForInt64(PrintInt64 As Int64,fReturn As Long)

第一パラメータ:表示するInt64型変数を入れてください。
第二パラメータ:リターンする場合はTRUEを、しない場合はFALSEを入れてください。
注意:Promptディレクティブが読み込まれている必要があります。
概要:Int64型変数を表示します。

※ここに説明されていない関数は説明されている関数を支えるために設計されてある隠し関数です。よって直接使用する事を推奨しません。
[/hide]

QWord型とInt64型用に、Print,Input,Str$,Valの4関数を作ってみました。
バグや明らかな書き間違い、質問や意見など何かあったらどうぞ。

_________________
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2006年6月24日(土) 20:57 
オフライン

登録日時: 2005年7月25日(月) 13:27
記事: 893
住所: 埼玉県東松山市
QWord型とInt64型用の、掛け算と割り算と余り算(Mod)を作りました。

関数のソースコード
[hide]
コード:
Function Mul_ForQWord(A As QWord,B As QWord) As QWord
	Dim i As Long
	Dim Ret As QWord
	If B=0 then
		Mul_ForQWord=0
		Exit Function
	End If
	If (B And 1)=1 then Ret=A else Ret=0
	For i=0 To 62
		B=B>>1
		A=A<<1
		If B=0 then Exit For
		If (B And 1)=1 then Ret=Ret+A
	Next i
	Mul_ForQWord=Ret
End Function

Function Mul_ForInt64(A As Int64,B As Int64) As Int64
	Dim FlagA As Long,FlagB As Long
	Dim C As Int64
	If A<0 then FlagA=1:A=0-A
	If B<0 then FlagB=1:B=0-B
	C=Mul_ForQWord(A As QWord,B As QWord)
	If FlagA=1 then C=0-C
	If FlagB=1 then C=0-C
	Mul_ForInt64=C
End Function

Function Div_ForQWord(A As QWord,B As QWord) As QWord
	'Ret=A/B
	Dim i As Long,C As QWord,Ret As QWord
	If A<B then
		Div_ForQWord=0
		Exit Function
	ElseIf A=B then
		Div_ForQWord=1
		Exit Function
	ElseIf B=0 then
		'0除算は出来ません。
		Div_ForQWord=&HFFFFFFFFFFFFFFFF
		debug
		Exit Function
	End If
	C=A
	i=0
	Do
		i+=1
		A=A>>1
		If A<=B then Exit Do
	Loop
	If A=B then
		Div_ForQWord=1<<i
		Exit Function
	End If
	i-=1
	C=C-(B<<i)
	Ret=1<<i
	While TRUE
		i-=1
		A=C>>i
		If A>=B then
			Ret=Ret+(1<<i)
			C=C-(B<<i)
		End If
		If C=0 then
			Exit While
		End If
		If i=0 then Exit While
	Wend
	Div_ForQWord=Ret
End Function

Function Div_ForInt64(A As Int64,B As Int64) As Int64
	Dim FlagA As Long,FlagB As Long
	Dim C As Int64
	If A<0 then FlagA=1:A=0-A
	If B<0 then FlagB=1:B=0-B
	C=Div_ForQWord(A As QWord,B As QWord)
	If FlagA=1 then C=0-C
	If FlagB=1 then C=0-C
	Div_ForInt64=C
End Function

Function Mod_ForQWord(A As QWord,B As QWord) As QWord
	Mod_ForQWord=A-Mul_ForQWord(Div_ForQWord(A,B),B)
End Function

Function Mod_ForInt64(A As Int64,B As Int64) As Int64
	Mod_ForInt64=A-Mul_ForInt64(Div_ForInt64(A,B),B)
End Function
[/hide]

各関数の説明

[hide=ここをクリックすると各関数の説明が表示されます。]
Mul_ForQWord(A As QWord,B As QWord) As QWord
第一引数:掛けられる数を指定します。
第二引数:掛ける数を指定します。
返り値:掛け算の結果が返ります。
備考:この関数では符号無し掛け算を行います。

Mul_ForInt64(A As Int64,B As Int64) As Int64
第一引数:掛けられる数を指定します。
第二引数:掛ける数を指定します。
返り値:掛け算の結果が返ります。
備考:この関数では符号有り掛け算を行います。ただし、少し手を抜いているので符号無し版を同時に定義しなければ使えません。

Div_ForQWord(A As QWord,B As QWord) As QWord
第一引数:割られる数を指定します。
第二引数:割る数を指定します。
返り値:割り算の結果が返ります。
備考:この関数では符号無し割り算を行います。

Div_ForInt64(A As Int64,B As Int64) As Int64
第一引数:割られる数を指定します。
第二引数:割る数を指定します。
返り値:割り算の結果が返ります。
備考:この関数では符号有り割り算を行います。ただし、少し手を抜いているので符号無し版を同時に定義しなければ使えません。

Mod_ForQWord(A As QWord,B As QWord) As QWord
第一引数:割られる数を指定します。
第二引数:割る数を指定します。
返り値:割り算の余りを返します。
備考:この関数では符号無し割り算を行います。

Mod_ForInt64(A As Int64,B As Int64) As Int64
第一引数:割られる数を指定します。
第二引数:割る数を指定します。
返り値:割り算の余りを返します。
備考:この関数では符号有り割り算を行います。

[/hide]

64ビット型の乗除算は、内部でDouble型に直してから行うらしく大きい数を行うとずれが生じます。
これらの関数ではシフト演算と加算減算のみの作業でこれらを行っているため、ずれは生じません。(ただし、普通に乗除算を行うより少し遅くなります。)

_________________
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2006年6月25日(日) 02:46 
オフライン

登録日時: 2005年5月31日(火) 07:49
記事: 162
64bit 版乗除算について
このアルゴリズムでは、乗算は 63 回、除算では条件を満たすまで無限ループ(!)を行っていますが、実際は乗算ならば 4 回の乗算と 3 回の加算、また除算ならば2 回の除算と 1 回の加算、その他細々としたビット演算で計算可能です。
と言うわけで作ってみたのですが、AB が期待したとおりに動作しなかったり、地雷を踏みまくったりでそれらを回避するために酷いコードになったので、ここに挙げるのは遠慮させてもらいます(ぉ
バグ報告レポートを作成していたのですが、結構な数になったのでくじけちまったorz


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2006年6月25日(日) 09:25 
オフライン

登録日時: 2005年5月31日(火) 17:59
記事: 895
住所: 東京都
既に書いた分だけでもバグ報告へ出したほうがよいと思います。

ところで整数除算演算子 \ を使ったときだけは64ビット整数でも浮動小数点演算を使っていないようです。
効率はあまり良くなさそうですが。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2006年6月25日(日) 12:21 
オフライン

登録日時: 2005年5月31日(火) 07:49
記事: 162
自分はいったい何をしているのだろう?という疑問に駆られたので、コーディング作業を中断して覗いてみましたよ、EXE の中を。
そしたら地雷原や不審な挙動の原因が少しだけ判りました。それは後ほどバグ板に提出する方向で。
ここでは調査結果の一部を報告します。

> 64ビット型の乗除算は、内部でDouble型に直してから行うらしく
こちらでは確認できませんでした。といっても QWord * QWord の組み合わせしか検証していませんが(汗
この現象が発生する条件を記してもらえればたすかります(バグ板で)。
なお QWord の乗算では、洗練された専用乗算ルーチンを使用して計算していました。

> ところで整数除算演算子 \ を使ったときだけは64ビット整数でも浮動小数点演算を使っていないようです。
> 効率はあまり良くなさそうですが。
こちらは確認できました。こちらも専用の関数を呼び出していますね。
効率は良くなさそうとのことですが、乗算関数同様に最適化されているように見えます。おそらく C++ が吐いたコードでしょうね。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2006年6月25日(日) 19:08 
オフライン

登録日時: 2005年7月25日(月) 13:27
記事: 893
住所: 埼玉県東松山市
>>tak
> 除算では条件を満たすまで無限ループ(!)を行っていますが
最高でも63回程度のはずです。(毎回iの数値を減算していって、i=0の時に抜け出すため。)

> こちらでは確認できませんでした。といっても QWord * QWord の組み合わせしか検証していませんが(汗
調べたところ、乗算の場合はQWord型のまま行うみたいなのですが、除算の場合にDouble型を使用しているようです。

> 効率は良くなさそうとのことですが、乗算関数同様に最適化されているように見えます。
比較したいところでしたが、手元にあるOpcodes.hlp(機械語の速度の表みたいなやつ)に載っていない命令がいくつもあったので比較できません。
誰か次の物についてクロック数が分かる人は教えてください。
FILD,FDIVRP,FSTP,FLD,FNSTCW,OpdSz,FLDCW,FISTP,FLDCW
実数除算のほうにクロック数が分からない未知の命令語がこれだけあります。
お手上げですね^^;
分かる部分だけで38クロックです。

整数除算の方は分かるやつばっかりなのですぐに算出できました。
途中で後分岐のループが一個入ってますが、それをスルーしたとして166クロック~228クロック、ループを一回繰り返すごとに+16クロックです。
ちなみにこのループを使わない場合もあって、そちらは158クロックでした。

ところで、QWord型に対してインクリメントを行った時に変数の値が壊れたような気がしました。誰か試してみてください。

_________________
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。


通報する
ページトップ
 記事の件名: バグ報告
投稿記事Posted: 2007年3月05日(月) 03:55 
Val関数にて、文字列中の「0」の部分が戻り値では「1」となるバグがあります。
隠し関数が原因のようなので、以下のように修正してみました。
コード:
Function Kakeru_QWord(A As Byte,B As QWord) As QWord
    Dim C As QWord
    Dim I As Long
    C = 0
    If A>0 then    'この行と
        For I=1 To A
            C = C + B
        Next I
    Else
        C = 0    'この行を修正
    End If
    Kakeru_QWord = C
End Function

Function Kakeru_Int64(A As Byte,B As Int64) As Int64
    Dim C As QWord
    Dim I As Long
    C = 0
    If A>0 then    '同じくこの行と
        For I=1 To A
            C = C + B
        Next I
    Else
        C = 0    'この行を修正
    End If
    Kakeru_Int64 = C
End Function


通報する
ページトップ
   
期間内表示:  ソート  
新しいトピックを投稿する  トピックへ返信する  [ 7 件の記事 ] 

All times are UTC+09:00


オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[0人]


トピック投稿:  可
返信投稿:  可
記事編集: 不可
記事削除: 不可
ファイル添付: 不可

検索:
ページ移動:  
cron
Powered by phpBB® Forum Software © phpBB Limited
Japanese translation principally by KONISHI Yohsuke