rand() 函數是php中常見的一個用于生成隨機數的函數。我們在開發中,常常需要使用到這個函數來模擬真實的數據或者進行一些測試方面的操作。
但是rand() 函數的性能一直是php開發中比較棘手的問題之一,因為每次調用rand() 函數,都會需要php重新計算一次隨機數。如果代碼中有很多次這樣的操作,那么執行起來就變得非常慢。但是,php給我們提供了一種方法,可以有效地解決這個問題,就是使用rand()緩存。
rand()緩存可以讓我們生成相同種子數值的隨機數,不會因為多次執行同一個種子數而產生不同結果。因此,我們可以把比較常用的種子數緩存起來,供以后的隨機數生成使用。這個方法可以大大提高代碼的執行效率。
## 以下是使用 rand()緩存 的示例代碼 <?php // 生成 0 開頭的隨機數 $rand_num = mt_rand(0, 100); // 構造種子數 $seed_num = sprintf("%08d", $rand_num); // 設置種子數 srand($seed_num); // 生成隨機數 $random_num = rand(0, 999999); echo $random_num; ?>
在這個示例中,我們使用了 mt_rand() 函數來生成一個 0 開頭的隨機數,然后把這個隨機數構造成了一個 8 位的種子數。接下來,通過 srand() 函數,我們把這個種子數設置為 rand() 函數的參數,之后就能夠使用 rand() 生成相同的隨機數了。
緩存會在with-contract模式下有效。如果你將函數嵌套在contract函數中,然后在使用緩存功能時,你應該可以看到相應的性能提高
## 下面是帶緩存的 contract 函數 contract A { function generateRandomNumber() public returns(uint256) { // 生成 0 開頭的隨機數 uint256 rand_num = uint256(keccak256(abi.encodePacked(block.difficulty, now, msg.sender))) % 100; // 構造種子數 uint64 seed_num = uint64(rand_num); // 設置種子數 rng.setSeed(seed_num); // 生成隨機數 uint256 random_num = rng.generateRandomUint(); return random_num; } } library RNG { struct Generator { uint64 seed; } function generateRandomUint(Generator storage _generator) internal returns (uint256) { // 獲取種子數 uint64 seed = _generator.seed; // 計算隨機數 uint32 random32 = uint32(keccak256(abi.encodePacked(seed))); uint256 random256 = uint256(keccak256(abi.encodePacked(random32, now, msg.sender, tx.hash, tx.origin, tx.gasprice))); // 更新種子數 _generator.seed = uint64(random256); return random256; } function setSeed(Generator storage _generator, uint64 _seed) public { require(_seed != 0, "Seed can not be null!"); _generator.seed = _seed; } }
在這個例子中,我們將緩存技術與智能合約相結合。我們先使用 keccak256 來獲取一個 0 到 99 的隨機數。在 geth 客戶端的控制臺中,你可以使用以下命令生成 10 個隨機數進行測試:
geth console > var a = web3.eth.contract([{"constant":false,"inputs":[],"name":"generateRandomNumber","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]).at("0x908a30bbfe9684e5f3cb9880ff856dd1e71d8d3c") undefined > for(var i = 0; i < 10; i++){console.log(a.generateRandomNumber().toString())}
測試結果中,你應該可以看到每次生成的隨機數都不同,但是都是符合在 0 到 999999 之間的范圍。這是因為我們在 rng.generateRandomUint() 方法中使用了帶有緩存的 rand() 函數生成的隨機數。
總之,rand() 緩存是一個非常有用的技術,可以大大提高代碼的執行效率。如果你在 PHP 或智能合約開發中有使用 rand() 函數的需求,那一定不要錯過這個技術??!