這份 class 相容性低,沒用 bitwise 方式完成,故效率也低。
union 存在之意義 ,大多是早期省記憶體之手法。由於 union + struct 之技巧必須同時考慮 padding 問題(這問題一向沒完全可攜性作法) 與 big / little endian 相容性問題,此例純是顯示,在 C++ 中,union 確實可以放 member function 當類別使用,且在操作浮點數上較為方便,缺點就如上述,完全沒考慮相容性與效能。
一般而言,使用 bitwise + pointer 處理,會比 union + struct 處理效率來得快,可攜性也較高。
Code Snippet
- /************************************************************************/
- /* */
- /* file : xfloat.h */
- /* date : 2012.7.26 */
- /* compiler : Visual C++ 2010 */
- /* author : EdisonX / Edison.Shih */
- /* */
- /************************************************************************/
- #ifndef XFLOAT_H_
- #define XFLOAT_H_
- #include <cstdint>
- #include <iostream>
- //////////////////////////////////////////////////////////////////////////
- // Float32
- #define FLT_MANT_BIT 23
- #define FLT_EXPO_BIT 8
- #define FLT_SIGN_BIT 1
- #define FLT_BASE_VAL (1 << (FLT_EXPO_BIT-1))-1
- union Float32{
- private:
- uint32_t m_Hex;
- float m_Val;
- // Consider Big endian is better
- struct {
- uint32_t m_mantissa :FLT_MANT_BIT;
- uint32_t m_exponment:FLT_EXPO_BIT;
- uint32_t m_sign :FLT_SIGN_BIT;
- };
- // set hex field
- void set_hex_field_(
- uint32_t sign, uint32_t exponment, uint32_t mantissa){
- m_sign = sign;
- m_exponment = exponment;
- m_mantissa = mantissa;
- }
- public:
- // ---------------------------------------------
- // Constructor
- Float32(uint32_t Hex=0) : m_Hex(Hex){};
- Float32(float Val) : m_Val(Val){};
- // ---------------------------------------------
- // checker function
- bool is_nan(){
- return
- m_exponment==((1<<FLT_EXPO_BIT)-1) &&
- m_mantissa!=0;
- }
- bool is_inf(){
- return
- m_exponment==((1<<FLT_EXPO_BIT)-1) &&
- m_mantissa==0;
- }
- bool is_normalize(){
- return !(
- m_exponment==0 && m_mantissa!=0
- );
- }
- // ---------------------------------------------
- // Set Special Value function
- // Not a number
- Float32& make_nan() {
- set_hex_field_(0, (1 << FLT_EXPO_BIT) - 1, 1);
- return *this;
- }
- // positive infinite
- Float32& make_inf() {
- set_hex_field_(0, (1 << FLT_EXPO_BIT) - 1, 0);
- return *this;
- }
- // normalize positive min value
- Float32& make_min(){
- set_hex_field_(0, 1, 0);
- return *this;
- }
- // normalize positive max value
- Float32& make_max(){
- set_hex_field_(0, (1<<FLT_EXPO_BIT)-2, (1<<FLT_MANT_BIT)-1);
- return *this;
- }
- // non-normalize positive min value
- Float32& make_min_n(){
- set_hex_field_(0, 0, 1);
- return *this;
- }
- // non-normalize positive max value
- Float32& make_max_n(){
- set_hex_field_(0, 0,(1<<FLT_MANT_BIT)-1);
- return *this;
- }
- // ---------------------------------------------
- // Set Field function
- Float32& set_mantissa_hex(const uint32_t mantissa){
- m_mantissa = mantissa;
- return *this;
- }
- Float32& set_exponment_hex(const uint32_t exponment){
- m_exponment = exponment;
- return *this;
- }
- Float32& set_exponment_dec(const int32_t exponment){
- m_exponment =
- static_cast<uint32_t>(exponment + FLT_BASE_VAL);
- return *this;
- }
- Float32& set_sign_hex(const uint32_t sign){
- m_sign = sign;
- return *this;
- }
- Float32& flip_sign(){
- m_sign = !m_sign;
- return *this;
- }
- // ---------------------------------------------
- // getter function
- uint32_t get_hex() const{
- return m_Hex;
- }
- uint32_t get_exponment_hex() const{
- return m_exponment;
- }
- int32_t get_exponment_dec() const{
- return
- static_cast<int32_t>(m_exponment) - FLT_BASE_VAL;
- }
- bool get_sign() const{
- return m_sign;
- }
- // -----------------------------------------
- // compare operator
- bool operator > (const Float32& flt) const{
- return m_Val > flt.m_Val;
- }
- bool operator < (const Float32& flt) const{
- return m_Val < flt.m_Val;
- }
- bool operator == (const Float32& flt) const{
- return m_Val == flt.m_Val;
- }
- bool operator >= (const Float32& flt) const{
- return m_Val >= flt.m_Val;
- }
- bool operator <= (const Float32& flt) const{
- return m_Val <= flt.m_Val;
- }
- // -----------------------------------------
- // assigned operator
- Float32& operator = (const Float32& flt) {
- if(this==&flt) return *this;
- m_Hex = flt.m_Hex;
- return *this;
- }
- Float32& operator = (const float& flt){
- m_Val = flt;
- return *this;
- }
- Float32& operator = (const uint32_t& flt_hex){
- m_Hex = flt_hex;
- return *this;
- }
- // -----------------------------------------
- // cast
- operator float() const { return m_Val; }
- operator uint32_t() const {return m_Hex; }
- // -----------------------------------------------
- // iostream function
- friend std::ostream& operator<<(std::ostream& os, const Float32& flt);
- friend std::istream& operator>>(std::istream& iis, Float32& flt);
- // -----------------------------------------------
- // math function
- friend Float32 frexp(Float32 f32, int *exponment);
- friend Float32 ldexp(Float32 f32, int exponment);
- };
- std::ostream& operator<<(std::ostream& os, const Float32& flt){
- os << flt.m_Val;
- return os;
- }
- std::istream& operator>>(std::istream& iis, Float32& flt){
- iis >> flt.m_Val;
- return iis;
- }
- Float32 frexp(Float32 f32, int *exponment)
- {
- *exponment = f32.m_exponment - FLT_BASE_VAL + 1;
- f32.set_exponment_dec(-1);
- return f32;
- }
- Float32 ldexp(Float32 f32, int exponment)
- {
- f32.m_Val*=2.0f;
- f32.m_exponment = exponment + FLT_BASE_VAL - 1;
- return f32;
- }
- //////////////////////////////////////////////////////////////////////////
- // Float64
- #define DBL_MANT_BIT 52
- #define DBL_EXPO_BIT 11
- #define DBL_SIGN_BIT 1
- #define DBL_BASE_VAL (1 << (DBL_EXPO_BIT-1))-1
- union Float64{
- private:
- uint64_t m_Hex;
- double m_Val;
- // Consider Big endian is better
- struct {
- uint64_t m_mantissa :DBL_MANT_BIT;
- uint64_t m_exponment:DBL_EXPO_BIT;
- uint64_t m_sign :DBL_SIGN_BIT;
- };
- // set hex field
- void set_hex_field_(
- uint64_t sign, uint64_t exponment, uint64_t mantissa){
- m_sign = sign;
- m_exponment = exponment;
- m_mantissa = mantissa;
- }
- public:
- // ---------------------------------------------
- // Constructor
- Float64(uint64_t Hex=0) : m_Hex(Hex){};
- Float64(double Val) : m_Val(Val){};
- // ---------------------------------------------
- // checker function
- bool is_nan(){
- return
- m_exponment==((1<<DBL_EXPO_BIT)-1) &&
- m_mantissa!=0;
- }
- bool is_inf(){
- return
- m_exponment==((1<<DBL_EXPO_BIT)-1) &&
- m_mantissa==0;
- }
- bool is_normalize(){
- return !(
- m_exponment==0 && m_mantissa!=0
- );
- }
- // ---------------------------------------------
- // Set Special Value function
- // Not a number
- Float64& make_nan() {
- set_hex_field_(0, (1 << DBL_EXPO_BIT) - 1, 1);
- return *this;
- }
- // positive infinite
- Float64& make_inf() {
- set_hex_field_(0, (1 << DBL_EXPO_BIT) - 1, 0);
- return *this;
- }
- // normalize positive min value
- Float64& make_min(){
- set_hex_field_(0, 1, 0);
- return *this;
- }
- // normalize positive max value
- Float64& make_max(){
- set_hex_field_(0, (1ULL<<DBL_EXPO_BIT)-2, (1ULL<<DBL_MANT_BIT)-1);
- return *this;
- }
- // non-normalize positive min value
- Float64& make_min_n(){
- set_hex_field_(0, 0, 1);
- return *this;
- }
- // non-normalize positive max value
- Float64& make_max_n(){
- set_hex_field_(0, 0,(1ULL<<DBL_MANT_BIT)-1);
- return *this;
- }
- // ---------------------------------------------
- // Set Field function
- Float64& set_mantissa_hex(const uint64_t mantissa){
- m_mantissa = mantissa;
- return *this;
- }
- Float64& set_exponment_hex(const uint64_t exponment){
- m_exponment = exponment;
- return *this;
- }
- Float64& set_exponment_dec(const int64_t exponment){
- m_exponment =
- static_cast<uint64_t>(exponment + DBL_BASE_VAL);
- return *this;
- }
- Float64& set_sign_hex(const uint64_t sign){
- m_sign = sign;
- return *this;
- }
- Float64& flip_sign(){
- m_sign = !m_sign;
- return *this;
- }
- // ---------------------------------------------
- // getter function
- uint64_t get_hex() const{
- return m_Hex;
- }
- uint64_t get_exponment_hex() const{
- return m_exponment;
- }
- int64_t get_exponment_dec() const{
- return
- static_cast<int64_t>(m_exponment) - DBL_BASE_VAL;
- }
- bool get_sign() const{
- return m_sign;
- }
- // -----------------------------------------
- // compare operator
- bool operator > (const Float64& flt) const{
- return m_Val > flt.m_Val;
- }
- bool operator < (const Float64& flt) const{
- return m_Val < flt.m_Val;
- }
- bool operator == (const Float64& flt) const{
- return m_Val == flt.m_Val;
- }
- bool operator >= (const Float64& flt) const{
- return m_Val >= flt.m_Val;
- }
- bool operator <= (const Float64& flt) const{
- return m_Val <= flt.m_Val;
- }
- // -----------------------------------------
- // assigned operator
- Float64& operator = (const Float64& flt) {
- if(this==&flt) return *this;
- m_Hex = flt.m_Hex;
- return *this;
- }
- Float64& operator = (const double& flt){
- m_Val = flt;
- return *this;
- }
- Float64& operator = (const uint64_t& flt_hex){
- m_Hex = flt_hex;
- return *this;
- }
- // -----------------------------------------
- // cast
- operator double() const { return m_Val; }
- operator uint64_t() const {return m_Hex; }
- // -----------------------------------------------
- // iostream function
- friend std::ostream& operator<<(std::ostream& os, const Float64& flt);
- friend std::istream& operator>>(std::istream& iis, Float64& flt);
- // -----------------------------------------------
- // math function
- friend Float64 frexp(Float64 f64, int *exponment);
- friend Float64 ldexp(Float64 f64, int exponment);
- };
- std::ostream& operator<<(std::ostream& os, const Float64& flt){
- os << flt.m_Val;
- return os;
- }
- std::istream& operator>>(std::istream& iis, Float64& flt){
- iis >> flt.m_Val;
- return iis;
- }
- Float64 frexp(Float64 f64, int *exponment)
- {
- *exponment = static_cast<int>(f64.m_exponment) - FLT_BASE_VAL + 1;
- f64.set_exponment_dec(-1);
- return f64;
- }
- Float64 ldexp(Float64 f64, int exponment)
- {
- f64.m_Val*=2.0;
- f64.m_exponment = static_cast<uint64_t>(
- exponment + FLT_BASE_VAL - 1 );
- return f64;
- }
- //////////////////////////////////////////////////////////////////////////
- #endif
全站熱搜
留言列表