2013-02-06 60 views
2

有誰知道一個開源的C或C++函數庫,它具有實現人們可能想要的每個整數除法模式的函數?可能的行爲(對於陽性結果):int劃分庫?

round_down, round_up, 
round_to_nearest_with_ties_rounding_up, 
round_to_nearest_with_ties_rounding_down, 
round_to_nearest_with_ties_rounding_to_even, 
round_to_nearest_with_ties_rounding_to_odd 

與每個(除了舍入到偶數和舍入到奇數),其具有兩個變體

// (round relative to 0; -divide(-x, y) == divide(x, y)) 
negative_mirrors_positive, 
// (round relative to -Infinity; divide(x + C*y, y) == divide(x, y) + C) 
negative_continuous_with_positive 

我知道該怎麼寫,但肯定有人已經這樣做了嗎?

作爲一個例子,如果我們假設(這是常見和受權C++ 11),其內置有符號整數除法輪朝向零,而內置的模量爲與此一致,那麼

int divide_rounding_up_with_negative_mirroring_positive(int dividend, int divisor) { 
    // div+mod is often a single machine instruction. 
    const int quotient = dividend/divisor; 
    const int remainder = dividend % divisor; 
    // this ?:'s condition equals whether quotient is positive, 
    // but we compute it without depending on quotient for speed 
    // (instruction-level parallelism with the divide). 
    const int adjustment = (((dividend < 0) == (divisor < 0)) ? 1 : -1); 
    if(remainder != 0) { 
    return quotient + adjustment; 
    } 
    else { 
    return quotient; 
    } 
} 

加分點:多參數類型的工作;快速;可選地返回模量;不要爲任何參數值溢出(當然,除以零和MIN_INT/-1除外)。

如果我沒有找到這樣的庫,我會寫一個在C++ 11,鬆開,這裏鏈接到它的答案。

+1

C++ 11和更多的Boost 。但我不記得那些程度。 – chris

+2

有可能是沒有圖書館,因爲你可以通過添加0.5和鑄造爲int – technosaurus

+3

@technosaurus,獲得正常的四捨五入行爲'的std :: round'做這件事情。 – chris

回答

1

所以,我寫的東西。實現通常是醜陋的模板和按位代碼,但它運行良好。用法:

divide(dividend, divisor, rounding_strategy<...>()) 

其中rounding_strategy<round_up, negative_mirrors_positive>是一個示例策略;請參閱我的問題或源代碼中的變體列表。 https://github.com/idupree/Lasercake/blob/ee2ce96d33cad10d376c6c5feb34805ab44862ac/data_structures/numbers.hpp#L80

僅取決於C++ 11 [*],單元測試(使用升壓測試框架)起始於https://github.com/idupree/Lasercake/blob/ee2ce96d33cad10d376c6c5feb34805ab44862ac/tests/misc_utils_tests.cpp#L38

它是多態的,體面的速度,並且不溢出,但目前不返回模量。 (和boost :: make_signed和boost :: enable_if_c,它們很容易替換爲std :: make_signed和std :: enable_if,以及我們的caller_error_if(),它可以用assert()替換。或者如果(..){throw ..}或刪除,您可以忽略並刪除文件的其餘部分,假設您對其他東西不感興趣)。

每個divide_impl的代碼可以適應C用例如,替換每個T. int和T(CONSTANT)和CONSTANT。在round_to_nearest_ *變體的情況下,您可能希望使舍入類型成爲運行時參數或創建代碼的六個副本(每個處理的每個不同舍入變體都有一個副本)。代碼依靠'/'四捨五入到零,這是常見的,也由C11(std draft N1570 6.5.5.6)以及C++ 11指定。對於C89/C++ 98的兼容性,它可以使用stdlib.h div()/ ldiv(),它們保證向零舍入(參見http://www.linuxmanpages.com/man3/div.3.php,http://en.cppreference.com/w/cpp/numeric/math/div