• ベストアンサー

有効桁数の数え方・誤差

actionscriptをやっているのですが、有効桁数の数え方がよくわかりません。 たとえばNumber(有効桁数15桁)で public function sample() { var tf : TextField = new TextField(); var suuji : Number = 0.999; var suuji2 : Number = 1.001; var kekka : Number; kekka = suuji2 - suuji; tf.text = "" suuji2 + "-" suuji + "=" + kekka; } というものを実行させた場合kekkaが0.0019999999999998908になるのですが、この際の各々の変数の有効桁数は suuji 3桁 suuji2 4桁 kekka 0桁 という解釈で良いのでしょうか? そしてこの場合は桁落ちが起きていると言えるのでしょうか? また、この際にkekkaに誤差がでるのはNumberの有効桁数が15桁であるため、それ以降の桁に勝手に数字が入れられるということでしょうか? (0.999が勝手に0.9990000000000001092になる) もうひとつわからないことがあって、これは型の有効桁数を調べるプログラムなんですけど、 public function sample2() { var n : int; var sb : Number,sn : Number,t : Number; var tf : TextField = new TextField(); tf.border = true; tf.width = 400; tf.height = 300; n = 1; sn = t = 1.0; sb =0.0; while(sn != sb){ tf.appendText(n + ":" + sn + ":" + t + "\n"); n++; t = t / 10.0; sb = sn; sn = sb + t; } addChild(tf); } を実行すると 1:1:1 2:1.1:0.1 3:1.11:0.01 4:1.111:0.001 5:1.1111:0.0001 6:1.11111:0.00001 7:1.111111:0.0000010000000000000002 8:1.1111111:1.0000000000000002e-7 9:1.11111111:1.0000000000000002e-8 10:1.111111111:1.0000000000000003e-9 11:1.1111111111:1.0000000000000003e-10 12:1.11111111111:1.0000000000000003e-11 13:1.1111111111110001:1.0000000000000002e-12 14:1.1111111111111:1.0000000000000002e-13 15:1.11111111111111:1.0000000000000002e-14 16:1.1111111111111112:1e-15 と表示されるのですが、これだと16行目の有効桁数が16桁になっているのでしょうか? しかしそれだと型の有効桁数と矛盾するので、たまたま16桁目が1だっただけで有効桁数は15ということでしょうか? また、tに2や3の数字が勝手に入れらていますが、これも上記のように有効桁数ではない部分に勝手に数字を入れられているということでしょうか? 長文、また見辛く申し訳ありません。

  • ahys
  • お礼率61% (8/13)

質問者が選んだベストアンサー

  • ベストアンサー
  • goosyu
  • ベストアンサー率58% (36/62)
回答No.2

>var suuji : Number = 0.999; >var suuji2 : Number = 1.001; >というものを実行させた場合kekkaが0.0019999999999998908になるのですが、この >際の各々の変数の有効桁数は >suuji 3桁 >suuji2 4桁 >kekka 0桁 >という解釈で良いのでしょうか? Number型であれば有効桁数は変わりません。 ただし数学的な有効桁数の定義としてsuuji,suuji2が3桁,4桁というのはあっている気はします。 次のように各変数の値は格納されています。(10進数表記と16進数表記) suuji = 0.99900000000000000(3feff7ce d916872b) suuji2= 1.0009999999999999(3ff00418 9374bc6a) kekka = 0.0019999999999998908(3f60624d d2f1a900) 理想 = 0.0020000000000000000(3f60624d d2f1a9fc) 見てわかるとおりsuuji2は既に1.001ではありません。 suuji2を丸め誤差を考え表示した場合は1.001となります。 2進数を使った浮動小数点ではで表せない10進数の小数がある為,浮動小数を表示する場合は表示桁数を参考に丸め誤差を補正しています。 kekkaも同じく丸めによる値を補正すれば0.002と表示されるはずです。 >そしてこの場合は桁落ちが起きていると言えるのでしょうか? この2つの値はほぼ同じ値での引き算なので,桁落ちは発生しています。 >また、この際にkekkaに誤差がでるのはNumberの有効桁数が15桁であるため、それ以降の桁に勝手に数字が入れられるということでしょうか? 浮動小数点は2進数で計算を行っている為,少しだけ違います。実際に計算結果を記述しましたので桁落ちした点を見てイメージしてください。 suuji = 0x3feff7ce d916872b 0011 1111 1110 1111 1111 0111 1100 1110 1101 1001 0001 0110 1000 0111 0010 1011 011 1111 1110 = 1022 - 1023 = -1なので2^-1 1.1111 1111 0111 1100 1110 1101 1001 0001 0110 1000 0111 0010 1011 0.1 1111 1111 0111 1100 1110 1101 1001 0001 0110 1000 0111 0010 1011 =0.11111111101111100111011011001000101101000011100101011 ←2進数での小数表現 suuji2 = 0x3ff00418 9374bc6a 0011 1111 1111 0000 0000 0100 0001 1000 1001 0011 0111 0100 1011 1100 0110 1010 011 1111 1111 = 1023 - 1023 = 0なので2^0 1.0000 0000 0100 0001 1000 1001 0011 0111 0100 1011 1100 0110 1010 1.0000 0000 0100 0001 1000 1001 0011 0111 0100 1011 1100 0110 1010 =1.0000000001000001100010010011011101001011110001101010 ←2進数での小数表現 kekka = 0x3f60624d d2f1a900 0 01111110110 00000110001001001101110100101111000110101001 00000000 suuji2 - suujiの計算は次のようになります。(単純に2進数の引き算)  1.0000000001000001100010010011011101001011110001101010 -0.11111111101111100111011011001000101101000011100101011 ---------------------------------------------------------  0.00000000100000110001001001101110100101111000110101001 正規化して浮動小数点表記  1.00000110001001001101110100101111000110101001 * 2 ^-9 -9 + 1023 = 1014 0 01111110110 00000110001001001101110100101111000110101001 ******** 桁落ち6ビット この計算結果とkekkaは同じになります。 >(0.999が勝手に0.9990000000000001092になる) これは0.999が浮動小数点で表せない為です。有効桁数を超える部分は表示されても意味を持たないと考えるべきです。

ahys
質問者

お礼

丁寧な回答ありがとうございます! 浮動小数点数の仕組みの理解ができました。 ですが、この場合桁落ち6ビットではなく8ビットですよね? また、 >(0.999が勝手に0.9990000000000001092になる) と書きましたがそうではなく、suuji2の方が浮動小数点数では表せない数字だったため計算結果がおかしくなったのですね。 本当にありがとうございました!

その他の回答 (3)

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.4

 まず64ビットの浮動小数点(倍精度 IEEE-754)では有効桁数が15桁~16桁(または約15桁)です。  ただしNumber型の有効桁数が15桁と記述されているであれば,値によって有効桁数が変わるというのは扱いづらいので15桁ということで整理されたと考えられます。  この為,[1.111111111111111]2は有効桁数16桁,[9.99999999999999]8は有効桁数15桁ということで問題はないと考えます。  つまりNumber型がどんな値でも保証出来る有効桁数は15桁まで。ただし値によっては16桁まで対応出来る場合があります。  ちなみに整数の有効桁数は2^53-1=9007199254740991,約15.9桁ですので同じく有効桁数15桁~16桁となります。 (この検証として9007199254740993は表せないことになります。)

ahys
質問者

お礼

分かりやすい回答ありがとうございます! 大変助かりました!

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.3

>ですが、この場合桁落ち6ビットではなく8ビットですよね? →寝ぼけていました。8ビットですね。 >と表示されるのですが、これだと16行目の有効桁数が16桁になっているのでしょうか? >しかしそれだと型の有効桁数と矛盾するので、たまたま16桁目が1だっただけで有効桁数は15ということでしょうか? →出来るだけ反映されていると思います。また有効桁数が16桁とすると例えば9.999999999999999が正しく表現される必要があります。(すいません未確認ですが。)

ahys
質問者

補足

9.999999999999999が9.999999999999998になりましたので有効桁数は16桁ではないみたいです。 Numberが表現できる値でもっとも近い数字が1.1111111111111112であり、有効桁数は15桁([1.11111111111111]12 []内が有効)という理解でよいでしょうか?

  • salsberry
  • ベストアンサー率69% (495/711)
回答No.1

> この際にkekkaに誤差がでるのはNumberの有効桁数が15桁であるため、それ以降の桁に勝手に数字が入れられるということでしょうか? > (0.999が勝手に0.9990000000000001092になる) > tに2や3の数字が勝手に入れらていますが、これも上記のように有効桁数ではない部分に勝手に数字を入れられているということでしょうか? 決して「勝手に入れられている」わけではありません。 たとえば10進数の0.1を2進数で表すと循環小数になってしまうので、有限桁数の2進数では10進数の0.1を正確に表すことは根本的にできないのです。 上記の出力で1.0/10.0の結果が端数なしにきちんと「0.1」と表示されているじゃないかと思われるかもしれませんが、実際には「0.1にできるだけ近い値」であって、正確な0.1ではありません。0.000001のあたりまで行くとそのわずかな誤差が表示にも出てきてしまっているだけです。

ahys
質問者

お礼

浮動小数点数の場合は表すことができない数字があるのですね。 回答ありがとうございました!

関連するQ&A

  • 有効桁数について

    ある数値を5回測定したとします A 5.039 B 5.075 C 5.092 D 5.064 E 5.058 有効桁数はすべて4桁ですよね? 次にA~Eの平均を取ると (A+B+C+D+E)/5=5.0656 と関数電卓で結果がでますが、4桁に丸めて5.066とすれば有効桁数の扱い方としては問題ないですか? そしてA~Eの平均の2乗をするときは、上記の平均を有効桁数4桁に丸めた5.066を2乗して (5.066)^2=25.664356 となり、そして5.066の有効桁数4桁に合わして25.66とすればいいのでしょうか? それとも平均の値を4桁に丸める前の電卓で出た値のまま2乗した後、最終的に4桁に丸めるのがいいのでしょうか?この数値だとどちらでやっても4桁にした値は変わりませんが・・・ 有効桁数の扱い方で問題があったら教えてください、また平均の2乗を求めるときはどちらが正しいのでしょうか? (平均の値の2乗は平均×平均なのだから平均の値を4桁にせず5桁として計算すると平均の2乗は有効桁数5桁と考えるので、やはり正しく平均の値を測定値の有効桁数4桁に丸めて出した平均の値を2乗する方が正しいですかね・・・)    また、上記の平均の計算をしたときのよな、「5」などの数字の有効桁数は何桁ですか?1桁なんでしょうか?もし1桁なら割り算をしているので有効桁数はいちばん桁数の少ないものに合わせるので有効桁数1となると平均の値が「5」となりおかしいとおもうんですが・・・ 上記の平均を取ったときの「5」や、測定回数の数値や、測定していない数で100で割れと書いてあったりしたときは、それらの数字の桁数も考えなければならないんでしょうか? 読みづらい文章かもしれませんが、ご回答待っています。

  • 桁数を求めるプログラム。

    入力した数字の桁数を表示させるというプログラムを考えています。 例) 135 この数字の桁数は3桁です。 などと表示させたいと思っています。 それで、私は入力した数値を10で割っていって入力した数値aがa<=0になったらループを終了して 何回ループしたかのカウンタで桁数を表示させようかと考えました。 たとえば135→13.5→1.35→0.135で整数部分が0となるのでループを打ち切って 3回繰り返したので3桁と表示させたいと思いました。 それでプログラムを考えてみたのですが、どうにもうまくいきいません。 どのように修正したら桁数が表示できるようになるでしょうか? #include <stdio.h> main() { double a=0; int n=1; scanf("%d",&a); while(1) { a=a/10.0; if(a<=0){ break; } n++; } printf("その数は%d桁です。\n",n); }

  • printfの%eで指数部分の桁数を調整する方法?

    書式指定子の%eで、8文字までで出力しなければなりません。 printf("data = %8.3e\n",data); 仮にdataが6.456e5の場合、 data = 6.456e+005 (既に10文字でオーバー) となってしまい、指数部の桁数が3桁になってしまうと 有効数字部分が少なくなってしまうので、 指数部を、1桁にする方法はあるのでしょうか? こんな感じで出力できるでしょうか? data = 6.456e+5

  • 文字列の修正

    初心者です よろしくお願いします Excel2010で次のようなことがしたいです 列のセルには次のような文字列が入っています  文字列 No.3 とか No.26 とか No.302 とかです  要するに「No.」の後に数字のところが 1桁 または 2桁 または 3桁です やりたいことは No.3はNo.003に No.26はNo.026にと 桁数を3桁に揃わせたいのです 関数にそのようにするものがあるのでしょうか? またあれば 同時に使い方も教えて頂きたいです よろしくお願いします。

  • アクションスクリプト ビットマップデータ 描画

    Flashゲーム作成のため、アクションスクリプトを学び始めた初心者です。 ゲーム作成中にプレイヤーがミスをした場合、"MISS!!"という文字を画面に描画し、下から上へスクロールさせる処理を考えています。 ビットマップデータにテキストフィールドで指定したテキストを描画しているのですが、その描画位置を指定できなくて困っています。 canvas = new BitmapData(WIDTH, HEIGHT, true, 0x0);// 透明、初期色0x00000000 var bitmap:Bitmap = new Bitmap(canvas); bitmap.scaleX = bitmap.scaleY = 1;// 1倍表示 addChild(bitmap); var tf:TextField = new TextField(); tf.defaultTextFormat = new TextFormat("MS ゴシック", 50, 0xFF0E0E ,true); tf.width = stage.stageWidth; // 幅 tf.height = 50; tf.autoSize = TextFieldAutoSize.CENTER; tf.y = 240; tf.text = "MISS!!"; canvas.draw(tf); これで実行すると、画面上にMISS!!と表示されて、tf=240が適応されません、どうしたらテキストの表示位置の縦方向の位置を変えることができるのでしょうか?教えていただきたいです。

    • ベストアンサー
    • Flash
  • Rというソフトの最小2乗法の結果について困ってます

    Rの出力結果で、「○○e+03」とは○○の10^3の、「○○e-02」とは10^-2の意味。というのは分かったのですが、どうやら有効桁数も示しているらしいのです。たとえば「3.03 e+05」の有効数字は3桁で、解答として出す際は303,000という表記で出すらしいのですが、なぜ3桁になるのか分かりません。 例えば、 出力結果が、           Estimate    Std. Error    t value    Pr(>|t|)           (Intercept)   -1.142e+05    3.668e+04   -3.115    0.00422 **           可処分所得   8.958e-01   1.724e-02    51.947   < 2e-16 *** のとき、 -1.142e+05なら-114,200と、8.958e-01なら0.8958として、 C_i=-114,200+0.8958Y_i という推定式で良いのでしょうか? あと、ついでなのですが、Pr(>|t|)の下の数値の横にある「**」や、「***」は何か意味があるのでしょうか?

  • ある文字列の最後の2桁で分解し配列にする方法・・・

    こんにちは。 ある12桁~24桁の数字に+1をした数字を表示しようとしています。 int型とfloat型が16桁以上の数字が扱えないようなので、おかしくなってしまいます・・・ 1111111111111111の数字に+1をすると 1.1111111111111E+15となります・・・。 これをどうにかできるようにしたいので、 この数字の最後の2桁で文字を分解し その2桁に+1をして、 再び 最後の2桁とそれ以前の文字列とを足して 元の桁数にしようと考えました。 しかし、この最後の2桁で文字を分解し、各変数か配列に収める方法がわかりません・・・ 何かよい方法もしくは関数などありませんか? どうか、よろしくお願いします。

    • ベストアンサー
    • PHP
  • 信号処理 SN(S/N)比の問題

    「ある信号を観測するとき,観測される信号y(t)は,次式に示すように,真の信号s(t)に,平均0,分散σ^2の定常な不規則雑音n(t)が加わったものとして表されるものとする。 y(t) = s(t)+ n(t) このとき,この信号をm回観測して算術平均を求めると,その期待される平均と分散は,s(t), σ, mを用いて,それぞれ(ア),(イ)と表される。このことから,振幅比でSN比を定義した場合,m回の観測の算術平均を求めることにより,1回のみの観測に比べて,SN比が (ウ)倍になることが期待でき,一定の雑音除去効果が得られることになる」 自分なりに出した答えが↓です.  解答:自分はs(t)は定数として扱いました s(t),n(t)の算術平均は  ・(1/m)*(Σs(t)) = s(t)  ・(1/m)*(Σn(t)) = 0  ∴(ア) = s(t) + 0 = s(t) s(t),n(t)の算術平均の分散は  ・var[(1/m)*(Σs(t))] = (1/m)^2 * Σvar[s(t)] = 0  ・var[(1/m)*(Σn(t))] = (1/m)^2 * Σvar[n(t)] = σ^2 / m 今s(t),n(t)は独立なので,y(t)の分散は上の二つの和になる  ∴(イ) = 0 + σ^2 / m = σ^2 / m SN比 = (真の信号の分散値) / (雑音の分散値)より  ・一回の観測時のSN比(m=1) = 0 / σ^2 = 0  ・m回の観測時のSN比 = 0 / (σ^2/m) = 0  となり(ウ)を求めることが出来ません.(;^^  「s(t)の算術平均値,分散値」を求めるところが怪しい気がしますが・・・よく分かりませんでした.    どなたか詳しい方がいらっしゃればお願いします.

  • アクセス 取り込み時に、桁数(テキスト型)を合わせたい

    CSVファイル(1ファイルあたり、2~4万件のデータ)をアクセスに取り込んで、作業しています。 桁数が異なる列が2箇所あるので、取り込み時に桁数を合わせたいと思います。 テーブルのフィールド・プロパティで、(テキスト型→数値型、書式→"000")として試してみましたが、 元のデータがアルファベット混じりのテキスト型のためか、上手くいきませんでした。 エクセルに出力して、text関数を使う方法もあるのですが、なんせデーター量が多いので、 出来ればアクセスで作業してしまいたいと思います。 マクロが設定されていますので、どこかに関数を入れればよいのかと思いますが、 アクセスのマクロは経験がないので、よくわかりません。 何か良い方法があれば、ご教授下さい。よろしくお願い致します。 CSVファイル: 53列 1ファイルあたり、2~4万件のデータ 桁数が異なる列: (1)O列(8桁と11桁(アルファベット含む)が混在) →8桁のものの頭に「000」を付け加えて、テキスト型で11桁に揃えたい (2)Z列 (空欄と、2桁、3桁が混在) →頭に空欄は「000」、2桁は「0」を付け加えて、テキスト型で3桁に揃えたい マクロ:KMM**.csv 複数データを取り込み、トータルテーブル[T_KMM]を作成 →[T_KMM]を使用したクエリ[Q_KMM]にてデータ抽出→エクセルへ出力 Option Compare Database Private Sub TableLinkUpdate_Click() Dim TableName As String Dim ImportDef As String Dim CsvName As String Dim Fpath As String Dim Epath As String Const TableKMMs As String = "KMM" Const UKMM As String = "T_KMM" Set db = CurrentDb() DoCmd.OpenQuery "KMM削除" Fpath = Me.フォルダパス n = db.TableDefs.Count - 13 For i = 1 To n DoCmd.DeleteObject acTable, TableKMMs & i Next i TableName = TableKMMs ImportDef = "KMMimport" CsvName = "KMM.csv" With Application.FileSearch .LookIn = Fpath .NewSearch .FileName = CsvName If .Execute > 0 Then i = .FoundFiles.Count Else MsgBox CsvName & "ファイルが見つかりません。", vbOKOnly, "エラー" End If For n = 1 To i Fpath = .FoundFiles(n) DoCmd.TransferText acLinkDelim, ImportDef, TableName & n, Fpath, False strSQL = "" strSQL = "INSERT INTO " & UKMM strSQL = strSQL & " SELECT *" strSQL = strSQL & "FROM " & TableName & n db.Execute strSQL Next n End With Epath = Me.フォルダパス DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, "Q_KMM", Epath & "\費用.xls", True DoCmd.Close acForm, "MAIN" MsgBox "終わりました。", vbOKOnly, "更新・出力完了" End Sub

  • 有効数字N桁のマクロについて

    有効数字N桁の処理をするマクロ ROUND2(aa,NN) aa処理する数字、 NN:有効数字桁数 ROUND2 = Application.Round(aa, -Int(Application.Log(Abs(aa))) - 1 + nn) をつかって、有効数字N桁表示をさせるようにしています。これを使って1.012や0.304という数字を有効数字2桁で処理しセルに値を返すと1や0.3と表示してしまいます。 これを1.0や0.30といった形で有効数字で丸めた値そのままをセルに返したいのですが、どのようなマクロを追加すればよいのでしょうか? 説明がわかりにくいかとおもいますが、よろしくお願いします。

専門家に質問してみよう