2011-09-16 61 views
2

我想知道如何編寫我自己的函數來將一個浮動函數向下舍入。如何從零開始編寫std :: floor函數

是否可以通過設置表示逗號後的數字的浮點位爲0來完成此操作?

如果是,那我該如何訪問和修改這些位?

謝謝。

+1

一般情況下,與非整數類型的位做任何事情是不可移植的,還是安全。最簡單的方法是將其轉換爲整數,編譯器將爲您完成整個功能。 'int floor(float a){return(int)a;}' –

+0

有沒有辦法解決? 編輯:順便說一句,沒有真正的相關性,但我想要一個浮動下來,而不是整個 – xcrypt

+0

不便攜,安全,或容易。編輯:舍入到最近的整數或其他地方? –

回答

4

你可以在浮點數上做點事,但是正確地做到這一點取決於知道浮點二進制表達式究竟是什麼。對於大多數機器而言,這些天它的IEEE-754,這是相當直接的。例如,IEEE-754 32位浮點數有1個符號位,8個指數位和23個尾數位,所以你可以使用位移和掩碼來提取這些字段並對它們進行處理。這樣做TRUNC(圓朝0整數)是很容易的:

float trunc(float x) { 
    union { 
     float f; 
     uint32_t i; 
    } val; 
    val.f = x; 
    int exponent = (val.i >> 23) & 0xff; // extract the exponent field; 
    int fractional_bits = 127 + 23 - exponent; 
    if (fractional_bits > 23) // abs(x) < 1.0 
     return 0.0; 
    if (fractional_bits > 0) 
     val.i &= ~((1U << fractional_bits) - 1); 
    return val.f; 
} 

首先,我們提取指數字段,並用它來計算出有多少位 小數點後存在的數量。如果尾數的大小超過尾數,那麼我們只返回0.否則,如果至少有1,我們屏蔽(清除)許多低位。很簡單。我們忽略了反常規,NaN和無窮大她,但是這樣做沒有問題,因爲它們具有全0或全1的指數,這意味着我們最終將denorm轉換爲0(如果它們與小的一樣,正常數字),並保持NaN/Inf不變。

要做到地板,還就需要看牌,併發負數「上」向負無窮。

注意,這幾乎比使用專用浮點說明資訊肯定要慢,因此,如果您需要使用上有沒有原生支持浮點硬件浮點數這樣的事情真的是唯一有用的。或者如果你只是想玩,並瞭解這些東西如何在低水平上工作。

+0

維基百科說IEEE-754是8位指數,23位尾數。 –

+0

@Chriss Dodd澄清很多,謝謝。 – xcrypt

+0

當你說'大多數機器'這是否意味着它不是完​​全可移植的?你能指定嗎? – xcrypt

3

從頭開始定義。不,將你的浮點數代表逗號後的數字設置爲0的位不起作用。如果你看一下IEEE-754,你會看到你基本上所有的浮點數形式:

0.xyzxyzxyz 2^(abc) 

所以要實現地板,你可以得到xyzxyzxyz和移位由ABC + 1次離開了。放下休息。我建議你閱讀浮點數的二進制表示(上面的鏈接),這應該闡明我提出的解決方案。

注:您還需要照顧標誌位。您的號碼的尾數是關閉的127

下面是一個例子,比方說,你有多少PI:3.14 ...,你想獲得3

Pi的二進制表示爲

0 10000000 10010010000111111011011 

這轉化爲

sign = 0 ; e = 1 ; s = 110010010000111111011011 

以上我從Wikipedia直接獲得。由於e爲1.您會希望通過1 + 1 = 2向左•換檔,讓您得到11 => 3.

+0

你用了很多術語我不明白這樣做真的有關......你能給我一些鏈接來解釋這一切的一個位?編輯:我從來沒有真正搞砸了以前的位。我知道像移位這樣的邏輯運算,但就是這樣。 – xcrypt

+1

@xcrypt移位不是邏輯運算符。 :-) – corsiKa

+0

@glowcoder對不起,我的意思是位運算符 – xcrypt

0
#include <iostream> 
#include <iomanip> 

double round(double input, double roundto) { 
    return int(input/roundto) * roundto; 
} 

int main() { 
    double pi = 3.1415926353898; 
    double almostpi = round(pi, 0.0001); 
    std::cout << std::setprecision(14) << pi << '\n' << std::setprecision(14) << almostpi; 
} 

http://ideone.com/mdqFA 輸出:

3.1415926353898
3.1415

這比任何你可以想到的都要快得多。它可以在所有的計算機上運行(使用浮點數),而不只是一種類型。

+1

這不是太大的*地板*的,它看起來更像* *圓我 –

+0

'圓「我想把一個浮子倒下來,而不是四捨五入......」這個截斷答案出現在評論中,他說這是不對的。 –

+0

這會湊合起來。但我回答說,我知道如何做到這一點 – xcrypt