這份 class 相容性低,沒用 bitwise 方式完成,故效率也低。

union 存在之意義 ,大多是早期省記憶體之手法。由於 union + struct 之技巧必須同時考慮 padding 問題(這問題一向沒完全可攜性作法) 與 big / little endian 相容性問題,此例純是顯示,在 C++ 中,union 確實可以放 member function 當類別使用,且在操作浮點數上較為方便,缺點就如上述,完全沒考慮相容性與效能。

一般而言,使用 bitwise + pointer 處理,會比 union + struct 處理效率來得快,可攜性也較高。

 

Code Snippet
  1. /************************************************************************/
  2. /*                                                                      */
  3. /*     file         : xfloat.h                                          */
  4. /*     date         : 2012.7.26                                         */
  5. /*     compiler     : Visual C++ 2010                                   */
  6. /*     author       : EdisonX / Edison.Shih                             */
  7. /*                                                                      */
  8. /************************************************************************/
  9.  
  10. #ifndef XFLOAT_H_
  11. #define XFLOAT_H_
  12.  
  13. #include <cstdint>
  14. #include <iostream>
  15.  
  16. //////////////////////////////////////////////////////////////////////////
  17. // Float32
  18.  
  19. #define FLT_MANT_BIT 23
  20. #define FLT_EXPO_BIT 8
  21. #define FLT_SIGN_BIT 1
  22. #define FLT_BASE_VAL (1 << (FLT_EXPO_BIT-1))-1
  23.  
  24. union Float32{
  25. private:
  26.     uint32_t m_Hex;
  27.     float    m_Val;
  28.  
  29.     // Consider Big endian is better
  30.     struct {
  31.         uint32_t m_mantissa :FLT_MANT_BIT;
  32.         uint32_t m_exponment:FLT_EXPO_BIT;
  33.         uint32_t m_sign     :FLT_SIGN_BIT;
  34.     };
  35.  
  36.     // set hex field
  37.     void set_hex_field_(
  38.         uint32_t sign, uint32_t exponment, uint32_t mantissa){
  39.             m_sign      = sign;
  40.             m_exponment = exponment;
  41.             m_mantissa  = mantissa;
  42.     }
  43. public:
  44.  
  45.     // ---------------------------------------------
  46.     // Constructor
  47.     Float32(uint32_t Hex=0) : m_Hex(Hex){};
  48.     Float32(float Val) : m_Val(Val){};
  49.  
  50.     // ---------------------------------------------
  51.     // checker function
  52.     bool is_nan(){
  53.         return
  54.             m_exponment==((1<<FLT_EXPO_BIT)-1) &&
  55.             m_mantissa!=0;
  56.     }
  57.     bool is_inf(){
  58.         return
  59.             m_exponment==((1<<FLT_EXPO_BIT)-1) &&
  60.             m_mantissa==0;
  61.     }
  62.     bool is_normalize(){
  63.         return !(
  64.             m_exponment==0 && m_mantissa!=0
  65.             );
  66.     }
  67.  
  68.     // ---------------------------------------------
  69.     // Set Special Value function
  70.  
  71.     // Not a number
  72.     Float32& make_nan() {
  73.         set_hex_field_(0,  (1 << FLT_EXPO_BIT) - 1, 1);
  74.         return *this;
  75.     }
  76.  
  77.     // positive infinite
  78.     Float32& make_inf() {
  79.         set_hex_field_(0,  (1 << FLT_EXPO_BIT) - 1, 0);
  80.         return *this;
  81.     }
  82.  
  83.     // normalize positive min value
  84.     Float32& make_min(){
  85.         set_hex_field_(0,  1, 0);
  86.         return *this;
  87.     }
  88.  
  89.     // normalize positive max value
  90.     Float32& make_max(){
  91.         set_hex_field_(0, (1<<FLT_EXPO_BIT)-2, (1<<FLT_MANT_BIT)-1);
  92.         return *this;
  93.     }
  94.  
  95.     // non-normalize positive min value
  96.     Float32& make_min_n(){
  97.         set_hex_field_(0, 0, 1);
  98.         return *this;
  99.     }
  100.  
  101.     // non-normalize positive max value
  102.     Float32& make_max_n(){
  103.         set_hex_field_(0, 0,(1<<FLT_MANT_BIT)-1);
  104.         return *this;
  105.     }
  106.  
  107.     // ---------------------------------------------
  108.     // Set Field function
  109.  
  110.     Float32& set_mantissa_hex(const uint32_t mantissa){
  111.         m_mantissa = mantissa;
  112.         return *this;
  113.     }
  114.     Float32& set_exponment_hex(const uint32_t exponment){
  115.         m_exponment = exponment;
  116.         return *this;
  117.     }
  118.     Float32& set_exponment_dec(const int32_t exponment){
  119.         m_exponment =
  120.             static_cast<uint32_t>(exponment + FLT_BASE_VAL);
  121.         return *this;
  122.     }
  123.     Float32& set_sign_hex(const uint32_t sign){
  124.         m_sign = sign;
  125.         return *this;
  126.     }
  127.     Float32& flip_sign(){
  128.         m_sign = !m_sign;
  129.         return *this;
  130.     }
  131.  
  132.     // ---------------------------------------------
  133.     // getter function
  134.     uint32_t get_hex() const{
  135.         return m_Hex;
  136.     }
  137.     uint32_t get_exponment_hex() const{
  138.         return m_exponment;
  139.     }
  140.     int32_t get_exponment_dec() const{
  141.         return
  142.             static_cast<int32_t>(m_exponment) - FLT_BASE_VAL;
  143.     }
  144.     bool get_sign() const{
  145.         return m_sign;
  146.     }    
  147.     // -----------------------------------------
  148.     // compare operator
  149.     bool operator > (const Float32& flt) const{
  150.         return m_Val > flt.m_Val;
  151.     }
  152.     bool operator < (const Float32& flt) const{
  153.         return m_Val < flt.m_Val;
  154.     }
  155.     bool operator == (const Float32& flt) const{
  156.         return m_Val == flt.m_Val;
  157.     }
  158.     bool operator >= (const Float32& flt) const{
  159.         return m_Val >= flt.m_Val;
  160.     }
  161.     bool operator <= (const Float32& flt) const{
  162.         return m_Val <= flt.m_Val;
  163.     }
  164.  
  165.     // -----------------------------------------
  166.     // assigned operator
  167.     Float32& operator = (const Float32& flt) {
  168.         if(this==&flt) return *this;
  169.         m_Hex = flt.m_Hex;
  170.         return *this;
  171.     }
  172.     Float32& operator = (const float& flt){
  173.         m_Val = flt;
  174.         return *this;
  175.     }
  176.     Float32& operator = (const uint32_t& flt_hex){
  177.         m_Hex = flt_hex;
  178.         return *this;
  179.     }
  180.     // -----------------------------------------
  181.     // cast
  182.     operator float() const { return m_Val; }
  183.     operator uint32_t() const {return m_Hex; }
  184.  
  185.     // -----------------------------------------------
  186.     // iostream function
  187.  
  188.     friend std::ostream& operator<<(std::ostream& os, const Float32& flt);
  189.     friend std::istream& operator>>(std::istream& iis, Float32& flt);
  190.  
  191.     // -----------------------------------------------
  192.     // math function
  193.     friend Float32 frexp(Float32 f32, int *exponment);
  194.     friend Float32 ldexp(Float32 f32, int exponment);
  195. };
  196. std::ostream& operator<<(std::ostream& os, const Float32& flt){
  197.     os << flt.m_Val;
  198.     return os;
  199. }
  200. std::istream& operator>>(std::istream& iis, Float32& flt){
  201.     iis >> flt.m_Val;
  202.     return iis;
  203. }
  204. Float32 frexp(Float32 f32, int *exponment)
  205. {
  206.     *exponment = f32.m_exponment - FLT_BASE_VAL + 1;
  207.     f32.set_exponment_dec(-1);
  208.     return f32;
  209. }
  210. Float32 ldexp(Float32 f32, int exponment)
  211. {
  212.     f32.m_Val*=2.0f;
  213.     f32.m_exponment = exponment + FLT_BASE_VAL - 1;
  214.     return f32;
  215. }
  216. //////////////////////////////////////////////////////////////////////////
  217. // Float64
  218. #define DBL_MANT_BIT 52
  219. #define DBL_EXPO_BIT 11
  220. #define DBL_SIGN_BIT 1
  221. #define DBL_BASE_VAL (1 << (DBL_EXPO_BIT-1))-1
  222.  
  223. union Float64{
  224. private:
  225.     uint64_t m_Hex;
  226.     double    m_Val;
  227.  
  228.     // Consider Big endian is better
  229.     struct {
  230.         uint64_t m_mantissa :DBL_MANT_BIT;
  231.         uint64_t m_exponment:DBL_EXPO_BIT;
  232.         uint64_t m_sign     :DBL_SIGN_BIT;
  233.     };
  234.  
  235.     // set hex field
  236.     void set_hex_field_(
  237.         uint64_t sign, uint64_t exponment, uint64_t mantissa){
  238.             m_sign      = sign;
  239.             m_exponment = exponment;
  240.             m_mantissa  = mantissa;
  241.     }
  242. public:
  243.  
  244.     // ---------------------------------------------
  245.     // Constructor
  246.     Float64(uint64_t Hex=0) : m_Hex(Hex){};
  247.     Float64(double Val) : m_Val(Val){};
  248.  
  249.     // ---------------------------------------------
  250.     // checker function
  251.     bool is_nan(){
  252.         return
  253.             m_exponment==((1<<DBL_EXPO_BIT)-1) &&
  254.             m_mantissa!=0;
  255.     }
  256.     bool is_inf(){
  257.         return
  258.             m_exponment==((1<<DBL_EXPO_BIT)-1) &&
  259.             m_mantissa==0;
  260.     }
  261.     bool is_normalize(){
  262.         return !(
  263.             m_exponment==0 && m_mantissa!=0
  264.             );
  265.     }
  266.  
  267.     // ---------------------------------------------
  268.     // Set Special Value function
  269.  
  270.     // Not a number
  271.     Float64& make_nan() {
  272.         set_hex_field_(0,  (1 << DBL_EXPO_BIT) - 1, 1);
  273.         return *this;
  274.     }
  275.  
  276.     // positive infinite
  277.     Float64& make_inf() {
  278.         set_hex_field_(0,  (1 << DBL_EXPO_BIT) - 1, 0);
  279.         return *this;
  280.     }
  281.  
  282.     // normalize positive min value
  283.     Float64& make_min(){
  284.         set_hex_field_(0,  1, 0);
  285.         return *this;
  286.     }
  287.  
  288.     // normalize positive max value
  289.     Float64& make_max(){
  290.         set_hex_field_(0, (1ULL<<DBL_EXPO_BIT)-2, (1ULL<<DBL_MANT_BIT)-1);
  291.         return *this;
  292.     }
  293.  
  294.     // non-normalize positive min value
  295.     Float64& make_min_n(){
  296.         set_hex_field_(0, 0, 1);
  297.         return *this;
  298.     }
  299.  
  300.     // non-normalize positive max value
  301.     Float64& make_max_n(){
  302.         set_hex_field_(0, 0,(1ULL<<DBL_MANT_BIT)-1);
  303.         return *this;
  304.     }
  305.  
  306.     // ---------------------------------------------
  307.     // Set Field function
  308.  
  309.     Float64& set_mantissa_hex(const uint64_t mantissa){
  310.         m_mantissa = mantissa;
  311.         return *this;
  312.     }
  313.     Float64& set_exponment_hex(const uint64_t exponment){
  314.         m_exponment = exponment;
  315.         return *this;
  316.     }
  317.     Float64& set_exponment_dec(const int64_t exponment){
  318.         m_exponment =
  319.             static_cast<uint64_t>(exponment + DBL_BASE_VAL);
  320.         return *this;
  321.     }
  322.     Float64& set_sign_hex(const uint64_t sign){
  323.         m_sign = sign;
  324.         return *this;
  325.     }
  326.     Float64& flip_sign(){
  327.         m_sign = !m_sign;
  328.         return *this;
  329.     }
  330.  
  331.     // ---------------------------------------------
  332.     // getter function
  333.     uint64_t get_hex() const{
  334.         return m_Hex;
  335.     }
  336.     uint64_t get_exponment_hex() const{
  337.         return m_exponment;
  338.     }
  339.     int64_t get_exponment_dec() const{
  340.         return
  341.             static_cast<int64_t>(m_exponment) - DBL_BASE_VAL;
  342.     }
  343.     bool get_sign() const{
  344.         return m_sign;
  345.     }    
  346.     // -----------------------------------------
  347.     // compare operator
  348.     bool operator > (const Float64& flt) const{
  349.         return m_Val > flt.m_Val;
  350.     }
  351.     bool operator < (const Float64& flt) const{
  352.         return m_Val < flt.m_Val;
  353.     }
  354.     bool operator == (const Float64& flt) const{
  355.         return m_Val == flt.m_Val;
  356.     }
  357.     bool operator >= (const Float64& flt) const{
  358.         return m_Val >= flt.m_Val;
  359.     }
  360.     bool operator <= (const Float64& flt) const{
  361.         return m_Val <= flt.m_Val;
  362.     }
  363.  
  364.     // -----------------------------------------
  365.     // assigned operator
  366.     Float64& operator = (const Float64& flt) {
  367.         if(this==&flt) return *this;
  368.         m_Hex = flt.m_Hex;
  369.         return *this;
  370.     }
  371.     Float64& operator = (const double& flt){
  372.         m_Val = flt;
  373.         return *this;
  374.     }
  375.     Float64& operator = (const uint64_t& flt_hex){
  376.         m_Hex = flt_hex;
  377.         return *this;
  378.     }
  379.     // -----------------------------------------
  380.     // cast
  381.     operator double() const { return m_Val; }
  382.     operator uint64_t() const {return m_Hex; }
  383.  
  384.     // -----------------------------------------------
  385.     // iostream function
  386.  
  387.     friend std::ostream& operator<<(std::ostream& os, const Float64& flt);
  388.     friend std::istream& operator>>(std::istream& iis, Float64& flt);
  389.  
  390.     // -----------------------------------------------
  391.     // math function
  392.     friend Float64 frexp(Float64 f64, int *exponment);
  393.     friend Float64 ldexp(Float64 f64, int exponment);
  394. };
  395. std::ostream& operator<<(std::ostream& os, const Float64& flt){
  396.     os << flt.m_Val;
  397.     return os;
  398. }
  399. std::istream& operator>>(std::istream& iis, Float64& flt){
  400.     iis >> flt.m_Val;
  401.     return iis;
  402. }
  403. Float64 frexp(Float64 f64, int *exponment)
  404. {
  405.     *exponment = static_cast<int>(f64.m_exponment) - FLT_BASE_VAL + 1;
  406.     f64.set_exponment_dec(-1);
  407.     return f64;
  408. }
  409. Float64 ldexp(Float64 f64, int exponment)
  410. {
  411.     f64.m_Val*=2.0;
  412.     f64.m_exponment = static_cast<uint64_t>(
  413.         exponment + FLT_BASE_VAL - 1 );
  414.     return f64;
  415. }
  416. //////////////////////////////////////////////////////////////////////////
  417. #endif

edisonx 發表在 痞客邦 PIXNET 留言(0) 人氣()