同じ型の変数(var A,B:single)が有るとして
その値を入れ替える関数が有ったと思うのですが
どなたか教えて下さい。
A:=123.456;
B:=789.123;
関数(A,B); <--?
A=789.123
B=123.456
又、以前はsingle型に整数を代入すると小数点が勝手に付いた
と思うのですが、Delphi6ではそのまま保持しているようです
この違いについてご存知の方、お願いします。
2つの値を交換する関数があるかどうかは確認できませんでした。
VBだとSwapだったと思うのですが、DelphiのSwapは上位バイトと下位バイトを交換するだけでした。
この関数の場合、ロジックは簡単なので、1つユニットを作って、そこにSwapFloatなどとして作れば回避できますがどうでしょう。
僕は、見つからない関数などを別ユニットで作っておいて、見つけたときにその関数を交換するようにしています。
> 又、以前はsingle型に整数を代入すると小数点が勝手に付いた
> と思うのですが、Delphi6ではそのまま保持しているようです
そのまま保持というのは、どういう現象でしょうか。
つまり、
var
a: single;
begin
a := 12345;
b := @a;
Edit1.Text := intToHex(integer(b[0]), 2)
+ intToHex(integer(b[1]), 2)
+ intToHex(integer(b[2]), 2)
+ intToHex(integer(b[3]), 2);
とすると、Edit1(TEditコンポーネント)に、
39300000
と表示されるということでしょうか。
# 12345の16進数は、$00003039
Delphi5では、きちんとSingle型で代入できています。
# 00E44046と表示されました
それとも、Format('%f', a);としたときに、12345.00と表示されることでしょうか。
Delphi5では、'%f'のときは12345.00と表示されます。'%.0f'なら、12345と表示されます。
Delphi6では、省略したときに表示する桁数を変更したのかもしれません。
にしの さま
ありがとうございました
2つの値を交換する関数は、以前使ったような気がしたのですが
勘違いかもしれません。
Single型の件は質問を変更します
var n,m:single;
begin
n:=1.1;
m:=1.1;
edit1.Text:=floattostr(n+m);
end;
結果、2.20000004768372 となります。
0.00000004768372の誤差は、どこから来るのでしょうか?
ループ計算した場合には誤差が拡大すると思いますので
正しい計算をする方法は無いのでしょうか?
又、double型にすると上記桁数では、正確に表示されます
同じように最小桁で誤差が生じているのでしょうか?
この場合、floattostr(n)でも、1.1にはなりませんよね。
# うちの環境では1.10000002384186とでました
有効桁数が違うため、singleでは誤差がつき、doubleではつきません。
FloatToStr関数は、15桁の有効桁数で変換しています。
double型の有効桁数は、15〜16、一方、single型の有効桁数は7〜8。
もし気になるのでしたら、FloatToStrF関数で、フォーマットを指定して変換するとよいです。
> ループ計算した場合
ためしにしてみました。
procedure TForm1.Button2Click(Sender: TObject);
var
a,b: single;
n,m:single;
i, j : integer;
begin
n:=0;
m := 1.1;
a := 0;
b := 11;
for i := 0 to 999 do
begin
for j := 0 to 999 do
begin
n := n + m;
a := a + b;
end;
end;
Edit1.Text := FloatToStr(n);
Edit2.Text := FloatToStr(a);
end;
です。singleとdouble、両方試しました。
結果は、
singleの場合、
1.1を1000000回 1110920.5
11を1000000回 11000000
doubleの場合、
1.1を1000000回 1099999.99998869
11を1000000回 11000000
doubleでも誤差は生じます。
これは、内部で少数を2進数で持っているからだと思います。
もし、精度を上げたければ、100倍なり1000倍なりして、整数にしてから計算させたほうがよいです。
速度も速くなりますし。
にしの さま
解りやすい回答ありがとうございます
これは以前から気になっていたのですが
実際に三角関数の計算で頻繁に使用している
pi(3.1415926535897932385)の問題です。
例えば円周すれすれで接する交点を計算したときに
誤差により外れる場合があると思います。
piを整数にするにはLongword型でも収まらないので...
完全な計算は、やはり無理なのでしょうか?
桁落ちですか。
そういう場合は、ある程度精度を犠牲にして、=0などの、「点」を調べるための計算を、<0+n、>0−nなどの、範囲を調べる計算に変えるとうまくいくと思います。
また、計算方法を数学での公式でなく、くずした形で計算すると誤差が少なくなることがあります。
>参考文献「C言語による最新アルゴリズム事典」技術評論社 奥村晴彦著
大変参考になりました
有難うございました。
ツイート | ![]() |