作者tropical72 (藍影)
看板C_and_CPP
標題[問題] no math.h, 如何判斷一浮點數 是否為整數
時間Tue Sep 27 23:59:32 2011
原問題是,
在不調用 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
1F:推 VictorTom:一定要回避cast可能造成的問題的話, 小弟我想到的方式也 09/28 00:03
2F:→ VictorTom:是直接抓IEEE754的浮點表示法, 解出exponent與mentisa出 09/28 00:03
3F:→ VictorTom:來算, 理論上可以藉由bit expression找到一個rule來判斷 09/28 00:04
4F:→ VictorTom:一個浮點數是否為整數; 限定用754表示法儲存的數就是了. 09/28 00:04
5F:推 alongalone:不用library, 那你從資料結構下手吧....自己把double 09/28 00:04
6F:→ alongalone:從新組合成integer 的格式 09/28 00:05
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)
7F:推 ericinttu:好久好久沒看到這個浮點表示法了ORZ 發言之前先複習一下 09/28 00:12
8F:推 VictorTom:小弟以為, 計算exponent的值, 是否足以讓mentisa shift 09/28 00:16
9F:→ VictorTom:到成為1.xxxxxxxx(x為0or1)的正規表示式後, 小數點.之後 09/28 00:17
10F:→ VictorTom:全為0, 是的話即代表該數為整數(先不考慮超小數)@_@" 09/28 00:17
11F:→ VictorTom:所以應該不用去算出浮點數來, 計算bit位數應該就行了@@" 09/28 00:18
12F:推 ericinttu:跟VictorTom想法一致 09/28 00:20
14F:→ ericinttu:mentias 有幾個bits, 最多就是需要左shift幾次. 09/28 00:26
15F:→ tropical72:真的是晃然大悟!這樣 ceil/floor 也可類似搞出來了. 09/28 00:27
16F:→ tropical72:感謝各位. 09/28 00:27
17F:推 ericinttu:用簡單的說法(假如有講錯請鞭) 09/28 00:29
18F:→ ericinttu:IEEE754 是 1+8+23 bits. mentisa 用到左邊數來第幾位, 09/28 00:31
19F:→ ericinttu:它的exponent值就要有多少. 09/28 00:32
20F:→ ericinttu:有一些特例/邊界值, 可能要另外考慮 (還沒有檢查那些) 09/28 00:33
21F:→ tropical72:嗯,這樣效率變 find most right bit 問題,可解.感謝!! 09/28 00:37
23F:→ ericinttu:32位單精度之下, 零/負零/... 等等的情況都要考慮到. 09/28 00:57
26F:→ firejox:請愛用sprintf~~ 09/28 01:52
27F:→ tropical72:sprintf ? 字串分析嗎? 09/28 01:53
28F:→ tropical72:sprintf(buf, "%.16e", x); 再分析 buf 嗎?不就慢了? 09/28 01:54
29F:→ firejox:恩恩 是的 09/28 01:54
30F:→ tropical72:sprintf 確實也為一種解法便是, 謝謝 firejox 提供 ^^ 09/28 01:55
31F:→ firejox:可是能夠完善處理總比出錯好呀~~ 09/28 01:56
32F:→ tropical72:確實可能較完善,只是在面試這回答恐怕.. 09/28 02:09
※ 編輯: tropical72 來自: 180.177.78.41 (09/28 02:09)
33F:→ littleshan:sprintf要小心buffer overflow唷 09/28 02:48