[問題] no math.h, 如何判斷一浮點數 是否為整數

看板C_and_CPP作者 (藍影)時間14年前 (2011/09/27 23:59), 編輯推噓9(9024)
留言33則, 7人參與, 最新討論串1/3 (看更多)
原問題是,在不調用 math.h 下,如何判斷一個浮點數是不是整數? 類似的問題還有 ceil、floor、rounding ( return (int)(x+0.5); ) 以 ceil 為例,考慮正負號、完善些的的可能長得像這樣 double ceil(double x) { if( x==(int)x) return (int)x; else if(x > 0.0) return (int)(x+1); else return (int)(x); } 而在不調用 math.h 下,判斷一個浮點數是否為整數,寫起來可能像這樣 int IsInteger(double x) { return (int)(x)==x; } 上面這些是在看 blog 時,大多人面試給的答案,但我認為不算正確 ( 當然我不是面試官,我不知道他們是怎麼評量這些答案的 ) 用 cast 達到 ceil、floor、rounding、判斷整數還蠻常見的, 但我認為錯誤的關鍵是在於這種寫法完全乎視了 casting 所帶來之影響, 換句話說,上述任一函式,將 x 以 12345678901234567890.12 傳入, 這在 casting 時必會發生 error,造成不可預期之錯誤。 問題來了,我也不知道真正標準的,「判斷整數」、「模擬 ceil」,該如何做, 初步是有想過以 IEEE754 64bits 方式下去分析,但卻又一直想不透, 不知各位版友對於此問是否有其他想法? 謝謝各位不吝解惑。 -- YouLoveMe() ? LetItBe() : LetMeFree(); -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 180.177.78.41 tropical72:轉錄至看板 Programming 09/28 00:00

09/28 00:03, , 1F
一定要回避cast可能造成的問題的話, 小弟我想到的方式也
09/28 00:03, 1F

09/28 00:03, , 2F
是直接抓IEEE754的浮點表示法, 解出exponent與mentisa出
09/28 00:03, 2F

09/28 00:04, , 3F
來算, 理論上可以藉由bit expression找到一個rule來判斷
09/28 00:04, 3F

09/28 00:04, , 4F
一個浮點數是否為整數; 限定用754表示法儲存的數就是了.
09/28 00:04, 4F

09/28 00:04, , 5F
不用library, 那你從資料結構下手吧....自己把double
09/28 00:04, 5F

09/28 00:05, , 6F
從新組合成integer 的格式
09/28 00:05, 6F
VictorTom 與 alongalone 所提之方式與小弟想到的有同曲之妙, 唯目前即使以 unsigned long long * 去接出來,還是讓人感到難以著手。 ( 在想這應也是一小段演算法了吧 ? ) 想過方式為,先取得 B=2^(exp-basement),假設 matissa = 111101... 再以 (1+0.5) * B, (1+0.75) * B, (1 + 0.875) *B, 再去判斷最大可能之整數, 問題又落回去了, 「判斷浮點數為整數」。 ※ 編輯: tropical72 來自: 180.177.78.41 (09/28 00:10)

09/28 00:12, , 7F
好久好久沒看到這個浮點表示法了ORZ 發言之前先複習一下
09/28 00:12, 7F

09/28 00:16, , 8F
小弟以為, 計算exponent的值, 是否足以讓mentisa shift
09/28 00:16, 8F

09/28 00:17, , 9F
到成為1.xxxxxxxx(x為0or1)的正規表示式後, 小數點.之後
09/28 00:17, 9F

09/28 00:17, , 10F
全為0, 是的話即代表該數為整數(先不考慮超小數)@_@"
09/28 00:17, 10F

09/28 00:18, , 11F
所以應該不用去算出浮點數來, 計算bit位數應該就行了@@"
09/28 00:18, 11F

09/28 00:20, , 12F
跟VictorTom想法一致
09/28 00:20, 12F

09/28 00:26, , 14F
mentias 有幾個bits, 最多就是需要左shift幾次.
09/28 00:26, 14F

09/28 00:27, , 15F
真的是晃然大悟!這樣 ceil/floor 也可類似搞出來了.
09/28 00:27, 15F

09/28 00:27, , 16F
感謝各位.
09/28 00:27, 16F

09/28 00:29, , 17F
用簡單的說法(假如有講錯請鞭)
09/28 00:29, 17F

09/28 00:31, , 18F
IEEE754 是 1+8+23 bits. mentisa 用到左邊數來第幾位,
09/28 00:31, 18F

09/28 00:32, , 19F
它的exponent值就要有多少.
09/28 00:32, 19F

09/28 00:33, , 20F
有一些特例/邊界值, 可能要另外考慮 (還沒有檢查那些)
09/28 00:33, 20F

09/28 00:37, , 21F
嗯,這樣效率變 find most right bit 問題,可解.感謝!!
09/28 00:37, 21F

09/28 00:56, , 22F
09/28 00:56, 22F

09/28 00:57, , 23F
32位單精度之下, 零/負零/... 等等的情況都要考慮到.
09/28 00:57, 23F

09/28 01:16, , 24F

09/28 01:38, , 25F
謝謝 cutecpu, 補上union http://codepad.org/Sixd4u0n
09/28 01:38, 25F

09/28 01:52, , 26F
請愛用sprintf~~
09/28 01:52, 26F

09/28 01:53, , 27F
sprintf ? 字串分析嗎?
09/28 01:53, 27F

09/28 01:54, , 28F
sprintf(buf, "%.16e", x); 再分析 buf 嗎?不就慢了?
09/28 01:54, 28F

09/28 01:54, , 29F
恩恩 是的
09/28 01:54, 29F

09/28 01:55, , 30F
sprintf 確實也為一種解法便是, 謝謝 firejox 提供 ^^
09/28 01:55, 30F

09/28 01:56, , 31F
可是能夠完善處理總比出錯好呀~~
09/28 01:56, 31F

09/28 02:09, , 32F
確實可能較完善,只是在面試這回答恐怕..
09/28 02:09, 32F
※ 編輯: tropical72 來自: 180.177.78.41 (09/28 02:09)

09/28 02:48, , 33F
sprintf要小心buffer overflow唷
09/28 02:48, 33F
文章代碼(AID): #1EWVBeUp (C_and_CPP)
文章代碼(AID): #1EWVBeUp (C_and_CPP)