Last active
March 20, 2017 14:34
-
-
Save manzyun/183df65c808413bca052fc68821aeab7 to your computer and use it in GitHub Desktop.
Rewriting humansize.py to C++ from Dive into Python3. But, I can not compiling... I can not C++.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Origin: Your first Python program - Dive Into Python 3 | |
* http://www.diveintopython3.net/your-first-python-program.html | |
* | |
* Original Source: | |
* http://www.diveintopython3.net/your-first-python-program.html | |
*/ | |
#include <memory> | |
#include <iostream> | |
#include <map> | |
#include <array> | |
#include <string> | |
#include <exception> | |
void init(){ | |
std::map <int, std::array<std::string, 8>> SUFFIXES; | |
std::array<std::string, 8> human = {"KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}; | |
std::array<std::string, 8> digital = {"KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}; | |
SUFFIXES.insert(std::make_pair(1000, human)); | |
SUFFIXES.insert(std::make_pair(1024, digital)); | |
delete human; | |
delete digital; | |
} | |
std::string approximateSize(int size, bool* a_kilobyte_is_1024_bytes = true) { | |
/* Convert a file size to human-readable form. | |
* | |
* Keyword argments: | |
* size -- file size in bytes | |
* a_kilobyte_is_1024_bytes -- if true (default), use multiples of 1024 | |
* -- if false, use multiples of 1000 | |
* | |
* Returns: std::string | |
*/ | |
if(size < 0){ | |
throw std::value_error("number must be non-negative"); | |
} | |
std::unique_ptr<int> multiple = std::make_unique<int>(); | |
multiple = a_kilobyte_is_1024_bytes ? 1024 : 1000; | |
for(auto suffix = SUFFIXES[multiple].begin(); suffix != SUFFIXES[multiple]; ++suffix) { | |
std::unique_ptr<int> size = std::make_unique<int>(); | |
size /= multiple; | |
if(size < multiple){ | |
std::unique_ptr<std::string> str_size = std::make_unique<std::string>(); | |
std::unique_ptr<std::string> str_suffix = std::make_unique<std::string>(); | |
std::unique_ptr<std::string> re_str = std::make_unique<std::string>(); | |
str_size = std::to_string(size); | |
str_suffix = std::to_string(suffix); | |
re_str.append({str_size, ' ', str_suffix}); | |
return re_str; | |
} | |
} | |
} | |
int main() { | |
init(); | |
std::cout << approximateSize(1000000000000, false) << std::endl; | |
std::std::cout << approximateSize(1000000000000) << std::endl; | |
delete SUFFIXES; | |
} |
気持ち高速化したもの
http://melpon.org/wandbox/permlink/sEp0LaISUQd5XUer
改善点
- よく見たらもとのpythonのコード、snake_caseじゃんか、ならばこっちもそれに合わせる。
- operator overeloadを利用し、処理を
operator<<
に移すことで、std::stringstream
を一旦作ったりという中間オブジェクト生成を減らし微かに高速化
std::unordered_map
を使わない版
http://melpon.org/wandbox/permlink/52jPbw1uCscAX3Sp
改善点
- よく考えたらサフィックスは2通りしかないんだから、要素2の配列にして引数のboolを
operator[]
にそのまま渡すだけでいいやん。 - ということはその配列の構築、コンパイル時にできるよ!
- サフィックスの文字列を
std::string
に変換する作業が大幅に減ったよ!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
動くように直したもの
http://melpon.org/wandbox/permlink/gVmSdN3Nisr3dfm9
修正のポイント
raise ValueError('number too large')
が次元のはざまに飲み込まれているようなので、追加std::map
ではなくstd::unordered_map
にstd::unique_ptr
があるが、何がしたいのか謎。ヒープへのメモリー確保は現代においてものすごく重いので避けるべし。std::to_string
だと浮動小数点の文字列化のときに精度を指定できないので、仕方なくstd::stringstream
とマニピュレータを使うように。fmtlib/fmt使いたい。for...in
に当たるRange based-forがありますinit
関数いらないし、無駄にグローバル変数作らない。