none
整数型、浮動小数点型のBit表示 RRS feed

  • 質問

  • VC++2019で、STL勉強中です。

    template<>特殊化なるものを勉強しており、整数型、浮動小数点型のBIT表示を行う関数を作成し、
    整数型と浮動小数点型を分けるために、浮動小数点型のほうをテンプレートの特殊化で、
    対応してみようと思いました。

    浮動小数点型の特殊化の場合、float,doubleと二つ作成することで対応できたのですが、
    関数パラメータの特殊化(?)でなら、一つの関数で対応できそうなので、実装してみました。

    しかしながら、浮動小数点型BIT表示メソッド側の、switch文などが、冗長的で何か他の方法があればと思っています。

    もっとシンプルに実装できますでしょうか。
    アドバイスあれば教えてください。

    // 整数型値Bit表示
    template< typename T >
    void BitShowMethod(T n, typename std::enable_if<std::is_integral<T>::value >::type* = 0) {
    	int j = sizeof(T) * 8 - 1;
    	for (int i = sizeof(T) * 8 - 1; i >= 0; i--) {
    		std::cout << (n >> i & 0x1);
    	}
    	std::cout << std::endl;
    }
    
    // 浮動小数点型値Bit表示
    template< typename T >
    void BitShowMethod(T n, typename std::enable_if<std::is_floating_point<T>::value >::type* = 0) {
    
    	union {
    		T d;
    		long l;
    		long long ll;
    	}f;
    	f.d = n;
    
    	switch (sizeof(T))
    	{
    	case 4:
    		BitShowMethod(f.l);
    		break;
    	case 8:
    		BitShowMethod(f.ll);
    		break;
    	}
    }
    
    int main()
    {
    	int i = 1;
    	short s = 1;
    	long long ll = 1;
    	float f = -118.625;
    	double d = -118.625;
    
    	BitShowMethod(i);
    	BitShowMethod(s);
    	BitShowMethod(ll);
    	BitShowMethod(f);
    	BitShowMethod(d);
    }
    

    2020年10月23日 7:27

回答

  • そもそも場合分けしなくても表現できてしまうんですよね…。

    #include <array>
    template <class T>
    void BitShowMethod(T const& n) {
      auto arr = reinterpret_cast<std::array<unsigned char, sizeof(T)> const&>(n);
      for (auto it = arr.rbegin(); it != arr.rend(); it++)
        for (int j = 7; 0 <= j; j--)
          std::cout << (*it >> j & 0x1);
      std::cout << std::endl;
    }
    

    • 回答としてマーク Brillia 2020年10月26日 2:28
    2020年10月23日 14:56

すべての返信

  • こんな?

    template< typename T >
    void BitShowMethod(T n, typename std::enable_if<std::is_floating_point<T>::value >::type* = 0) {
        auto q = *reinterpret_cast<unsigned long long*>(&n);
        for (int i = sizeof(T) * 8 - 1; i >= 0; i--) {
            std::cout << (q >> i & 0x1);
        }
        std::cout << std::endl;
    }


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2020年10月23日 10:32
  • そもそも場合分けしなくても表現できてしまうんですよね…。

    #include <array>
    template <class T>
    void BitShowMethod(T const& n) {
      auto arr = reinterpret_cast<std::array<unsigned char, sizeof(T)> const&>(n);
      for (auto it = arr.rbegin(); it != arr.rend(); it++)
        for (int j = 7; 0 <= j; j--)
          std::cout << (*it >> j & 0x1);
      std::cout << std::endl;
    }
    

    • 回答としてマーク Brillia 2020年10月26日 2:28
    2020年10月23日 14:56
  • VS 2019 16.8 Preview 3以降でコンパイルオプション /std:c++latest を付けると、こう書けます。(bitsetは昔からある機能ですが)

    #include <array>
    #include <bitset>
    #include <ranges>
    template<class T>
    void BitShowMethod(T const& n) {
      auto arr = reinterpret_cast<std::array<unsigned char, sizeof n> const&>(n);
      for (auto b : arr | std::ranges::views::reverse)
        std::cout << std::bitset<8>{b};
      std::cout << std::endl;
    }
    

    最新のGCCだともう一歩進んで。

    #include <array>
    #include <bitset>
    #include <ranges>
    void BitShowMethod(auto n) {
      auto arr = reinterpret_cast<std::array<unsigned char, sizeof n> const&>(n);
      for (auto b : arr | std::ranges::views::reverse)
        std::cout << std::bitset<8>{b};
      std::cout << std::endl;
    }
    

    2020年10月23日 22:11