« Packrat Parsing を調べてみる (その2) | トップページ | 命令的な Lisp »

2009年4月 9日 (木)

Float 遊び

ソースコード:

/*
   float_play1.c

   see:
   http://msdn.microsoft.com/ja-jp/library/c9676k6h.aspx
*/

#include <stdio.h>
#include <float.h>

void print_fvalue(float v) {
  /*
    IEEE754 単精度
    ビット数: 符号 1 , 指数 8, 仮数 23
    仮数 先頭 1 ビットは省略される。
    指数 下駄(bias)は 127。
  */
  float *pfv = &v;
  unsigned int *piv = (unsigned int*)pfv;
  printf_s("[0] %x\n", *piv);
  printf_s("[1] %x\n", *piv >> 31);
  printf_s("[2] %d\n", (*piv << 1 >> 24) - 127);
  printf_s("[3] %x\n", *piv << 9 >> 8);
}

float get_test_fvalue() {
  float v;
  v = 0.1f;
  v = v * 10.0f;
  v = v / 10.0f;
  return v;
}

int test(unsigned int newControl,
         unsigned int mask) {
  unsigned int currentControl;
  errno_t err;
  float v;

  err = _controlfp_s(&currentControl, newControl, mask);
  if (err != 0) {
    printf_s("_controlfp_s failed!\n");
    return err;
  } else {
    v = get_test_fvalue();
    print_fvalue(v);
    if (v == 0.1f)
      printf_s("No problem?\n");
    else
      printf_s("Ouch!\n");
    return 0;
  }
}

int main() {
  int err;

  err = test(_RC_CHOP, _MCW_RC);
  if (err != 0) {
    return err;
  }
  err = test(_RC_UP, _MCW_RC);
  if (err != 0) {
    return err;
  }
  err = test(_RC_DOWN, _MCW_RC);
  if (err != 0) {
    return err;
  }
  err = test(_RC_NEAR, _MCW_RC);
  if (err != 0) {
    return err;
  }
  return 0;
}

ビルド:

>cl float_play1.c
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

float_play1.c
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:float_play1.exe
float_play1.obj

実行:

>float_play1.exe
[0] 3dcccccc
[1] 0
[2] -4
[3] 999998
Ouch!
[0] 3dcccccf
[1] 0
[2] -4
[3] 99999e
Ouch!
[0] 3dcccccc
[1] 0
[2] -4
[3] 999998
Ouch!
[0] 3dcccccd
[1] 0
[2] -4
[3] 99999a
No problem?

アセンブリ リスト より:


 fld DWORD PTR _v$[ebp]
 fcomp QWORD PTR __real@3fb99999a0000000
 fnstsw ax
 test ah, 68     ; 00000044H
 jp SHORT $LN2@test

つまり:

/* ただそれだけのこと。 */

参考:

浮動小数点演算ではまった話 - bkブログ

|

« Packrat Parsing を調べてみる (その2) | トップページ | 命令的な Lisp »

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/80472/29032031

この記事へのトラックバック一覧です: Float 遊び:

« Packrat Parsing を調べてみる (その2) | トップページ | 命令的な Lisp »