52817


c/c++で文字列への変換無しで小数点以下の桁数を求めたいです。  
e.g)  
1.0 -> 0  
1.1 -> 1  
0.001 -> 3

[code]

    float x= 0.4002;
    int i=0;
    while( x != floor(x) )
    {
      x*=10;
      ++i;
    }
    
[/code]

一応こんな方法は思いついたのですが、  
浮動小数だと正確に10倍されずに正しい桁数が出ないことが判明したので 正確に小数点以下の桁数を求める方法があれば教えてください。


CC BY-SA 4.0
2019-02-16T14:24:36.423
52816
2019-02-18T01:27:22.560
29398
question
c++ c
c/c++で文字列変換無しで小数点以下の桁数が求めたい


> 浮動小数だと正確に10倍されずに正しい桁数が出ない

そこまで理解されていればもう少しです。正確に10倍できないのと同じように `0.1` は正確には 0.9999999999...
を適当なところで四捨五入して `0.1000000000` とみなして扱っているに過ぎません。  
また有効精度は10進数で8桁程度であり、例えば1億辺りの値を扱うと１の位に誤差が現れ小数点以下の値は保持できなくなります。

以上を踏まえて、誤差をどこまで許容するかの問題でしかありません。

* * *

後は `x*=10;` のように演算を繰り返すと誤差が積算されていくため、`x * 100`、 `x *
1000`のようになるべく整数演算を行い、浮動小数点数の演算を1回で完了させることで誤差を抑えることができます。


CC BY-SA 4.0
2019-02-16T15:26:28.037
52817
2019-02-16T15:26:28.037
4236
52816
answer


外部ライブラリ
[Boost.Multiprecision](https://www.boost.org/libs/multiprecision/doc/html/index.html)
を利用可能であれば、基数10の任意精度浮動小数点数として計算することもできます。下記コードでは「基数10で100桁精度の浮動小数点数型」を利用しています。

[code]

    #include <cassert>
    #include <boost/multiprecision/cpp_dec_float.hpp>
    namespace mp = boost::multiprecision;
    
    // 基数10の100桁精度浮動小数点数型
    using dec_float = mp::number<mp::cpp_dec_float<100>>;
    
    int main()
    {
      dec_float x{"0.0123456789012345678901234567890123456789"};
      int i = 0;
      while( x != floor(x) )
      {
        x *= 10;
        ++i;
      }
      assert(i == 40);
    }
    
[/code]


CC BY-SA 4.0
2019-02-18T01:27:22.560
52841
2019-02-18T01:27:22.560
49
52816
answer