程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++檢查浮點類型能否轉換為整型

C++檢查浮點類型能否轉換為整型

編輯:C++入門知識

最近嘗試用Cocoa做一個四則運算計算器來練手,類似於Windows cmd: calc的那種。

畢竟這個東西算是我們項目組的入門練習,當年很多新人剛進來,老組長都會教他們用MFC/QT做個計算器來看看水平。由於各種原因,我當年倒是沒有受到這種“禮遇”,等我真正開始做軟件的時候,還是服務器端這樣的純C++代碼做得比較多。但是不做不知道,一做才發現UI的邏輯還是挺復雜的,比如說,按“1”是追加到當前顯示還是覆蓋現有的顯示呢,最後把邏輯弄清楚倒不是很麻煩,但要寫出好看的代碼還是有比較大的差距的。

以上都是前言,好像比較長……

要說的是,在這個過程中發現的問題,計算結果是浮點數,要怎麼判斷其是否能無損地轉換成整數,從而消除小數點後的一段無用的“0”,以更好地顯示。直接上代碼:
 1 template <typename FloatType>
 2 struct _floattype_meta
 3 {
 4 };
 5
 6 template<>
 7 struct _floattype_meta<float>
 8 {
 9     enum {
10         EXPO_OFFSET = 23,
11         EXPO_LEN = 8
12     };
13
14     typedef uint32_t match_uint_type;
15 };
16
17 template<>
18 struct _floattype_meta<double>
19 {
20     enum {
21         EXPO_OFFSET = 52,
22         EXPO_LEN = 11
23     };
24
25     typedef uint64_t match_uint_type;
26 };
27
28 template <typename FloatType>
29 struct float_to_int
30 {
31     typedef struct _floattype_meta<FloatType> _meta;
32
33     bool operator() ( FloatType f, FloatType precision )
34     {
35         static const _meta::match_uint_type EXPO_MASK =
36             (~((~(_meta::match_uint_type)0) << _meta::EXPO_LEN )) << _meta::EXPO_OFFSET;
37         _meta::match_uint_type* pf = (_meta::match_uint_type*)&f;
38         uint32_t expo = ((*pf) & EXPO_MASK) >> _meta::EXPO_OFFSET;
39
40         static const uint32_t EXPO_FIRSTBIT_MASK = 1<< (_meta::EXPO_LEN-1);
41         static const uint32_t EXPO_BOUND = EXPO_FIRSTBIT_MASK - 1;
42         if ( expo >= EXPO_BOUND )
43         {
44             uint32_t to_right_move = expo - EXPO_BOUND;
45             if ( to_right_move >= _meta::EXPO_OFFSET )
46             {
47                 return true;
48             }
49             uint32_t cmp_len = _meta::EXPO_OFFSET - to_right_move;
50             _meta::match_uint_type mask = ~(~((_meta::match_uint_type)0) << cmp_len);
51             return (*pf&mask) ? false : true;
52         }
53         else
54         {
55             return ( f < precision && f > -precision ) ? true : false;
56         }
57     }
58 };
我的方法是通過浮點型的結構來進行判斷。

浮點類型一般結構如下:
|+/-|      exponent       |             tail                 |
對於float,指數部分為8字節,尾數部分為23字節。

對於double,指數部分為11字節,尾數部分為52字節。
其中指數部分是采用偏移方式的,比如float的指數部分為130,偏移值為127,即實際指數為130-127。
更詳細的請參考這裡。

判斷方法是,計算指數的值,根據偏移判斷小數點後的尾數,想得比較簡單,汗!
引入參數精度是為了判斷值小於1時達到某個阈值的時候可以將後面的小數略去。

Honestly,其實這個應該可以用sprintf,然後判斷小數點後的“0”來實現的,似乎更加簡單方便。
但是我覺得,作為一個“碼農”,重造輪子也是一種趣味嘛!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved