/** * Extended greatest common divisor * Compute the gcd as a multiple of the inputs: * gcd(a, b) = a*a' + b*b' * https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm * Knuth, The Art of Computer Programming, Volume 2, 4.5.2 Algorithm X. * * @param int $a * @param int $b * * @return array [gcd, a', b'] */ public static function extendedGCD(int $a, int $b) : array { // Base cases if ($a == 0) { return [$b, 0, 1]; } if ($b == 0) { return [$a, 1, 0]; } $x₂ = 1; $x₁ = 0; $y₂ = 0; $y₁ = 1; while ($b > 0) { $q = intdiv($a, $b); $r = $a % $b; $x = $x₂ - $q * $x₁; $y = $y₂ - $q * $y₁; $x₂ = $x₁; $x₁ = $x; $y₂ = $y₁; $y₁ = $y; $a = $b; $b = $r; } return [$a, $x₂, $y₂]; }
function main() { include_once 'numbers.php'; $numbers = listToArray($numberList); $digitCount = count($numbers[0]); $numberCount = count($numbers); $realSum = []; $startUnit = 0; /** * This use the elementary sum method from right to left. */ for ($i = $digitCount - 1; $i >= 0; $i--) { $sum = 0; for ($j = 0; $j < $numberCount; $j++) { $sum += intval($numbers[$j][$i]); } $sumSplit = array_reverse(str_split(strval($sum))); for ($k = 0; $k < count($sumSplit); $k++) { // NOTE: This null coalesce (??) only works on PHP 7 $realSum[$startUnit + $k] = $realSum[$startUnit + $k] ?? 0; // Get the sum by column $colSum = $realSum[$startUnit + $k] + intval($sumSplit[$k]); // Put remainder to the current result column $realSum[$startUnit + $k] = $colSum % 10; // If the column sum is >= 10, put the carry number to the next result column if ($colSum >= 10) { $realSum[$startUnit + $k + 1] = $realSum[$startUnit + $k + 1] ?? 0; // NOTE: This intdiv() is also only on PHP 7 $realSum[$startUnit + $k + 1] += intdiv($colSum, 10); } } $startUnit++; } var_dump(implode(array_reverse($realSum))); }
/** * Returns the largest integer value that is less than or equal to the algebraic quotient. * * @param integer $a The first argument, validated as an integer. * @param integer $b The second argument, validated as a non-zero integer. * * @return integer */ public static function floorDiv($a, $b) { $r = intdiv($a, $b); // If the signs are different and modulo not zero, round down. if (($a ^ $b) < 0 && $r * $b != $a) { $r--; } return $r; }
/** @return int */ public final function quotient() { if (!function_exists('intdiv')) { // This method isn't actually used internally by the library // currently so no hard dependency on these polyfills. // @codeCoverageIgnoreStart throw new \LogicException(sprintf('%s() requires the intdiv() function which was added in PHP 7' . ' you could use a polyfill such as michaelc/intdiv-compat or' . ' symfony/polyfill-php70 to provide this function', __METHOD__)); // @codeCoverageIgnoreEnd } return intdiv($this->result, $this->divisor); }
function lyn_convertToMinutes($seconds) { $sec = $seconds % 60; if (function_exists('intdiv')) { $min = intdiv($seconds, 60); } else { $min = ($seconds - $sec) / 60; } $sec = abs($sec); $sec = $sec < 10 ? '0' . $sec : $sec; return "{$min}:{$sec}"; }
/** * @param TweetCriteria $criteria * @return Tweet[] */ public function getTweets(TweetCriteria $criteria) { $results = array(); try { $refreshCursor = null; if ($criteria->getMaxTweets() == 0) { return $results; } do { $response = $this->getUrlResponse($criteria->getUsername(), $criteria->getSince(), $criteria->getUntil(), $criteria->getQuerySearch(), $refreshCursor); $refreshCursor = $response['min_position']; $htmlCrawler = new Crawler($response['items_html']); $tweetsCrawler = $htmlCrawler->filter('div.js-stream-tweet'); if ($tweetsCrawler->count() == 0) { break; } $tweetsCrawler->each(function ($tweet) use(&$results) { /** @var $tweet \Symfony\Component\DomCrawler\Crawler */ $username = $tweet->filter('span.username.js-action-profile-name b')->first()->text(); $text = str_replace('[^\\u0000-\\uFFFF]', '', $tweet->filter('p.js-tweet-text')->first()->text()); $retweets = intval(str_replace(',', '', $tweet->filter('span.ProfileTweet-action--retweet span.ProfileTweet-actionCount')->first()->attr('data-tweet-stat-count'))); $favorites = intval(str_replace(',', '', $tweet->filter('span.ProfileTweet-action--favorite span.ProfileTweet-actionCount')->first()->attr('data-tweet-stat-count'))); $date = new \DateTime('@' . intdiv(intval($tweet->filter('small.time span.js-short-timestamp')->first()->attr('data-time-ms')), 1000)); $id = $tweet->first()->attr('data-tweet-id'); $permalink = $tweet->first()->attr('data-permalink-path'); preg_match("(@\\w*)", $text, $mentions); preg_match("(#\\w*)", $text, $hashtags); $geo = ''; $geoElement = $tweet->filter('span.Tweet-geo')->first(); if ($geoElement->count() > 0) { $geo = $geoElement->attr('title'); } $resultTweet = new Tweet(); $resultTweet->setId($id); $resultTweet->setPermalink("https://twitter.com" . $permalink); $resultTweet->setUsername($username); $resultTweet->setText($text); $resultTweet->setDate($date); $resultTweet->setRetweets($retweets); $resultTweet->setFavorites($favorites); $resultTweet->setMentions($mentions); $resultTweet->setHashtags($hashtags); $resultTweet->setGeo($geo); $results[] = $resultTweet; }); } while (count($results) < $criteria->getMaxTweets()); } catch (\Exception $e) { $this->handleException($e); return $results; } return $results; }
/** * Find index for a value based * * @param mixed $value * @param int $compareLimit * @return int */ protected function findIndex($value, int $compareLimit) : int { $begin = 0; $end = count($this->values) - 1; while ($begin <= $end) { $middle = intdiv($begin + $end, 2); if (($this->values[$middle] <=> $value) <= $compareLimit) { $begin = $middle + 1; continue; } $end = $middle - 1; } return $begin; }
function convertMetersToYards($meters) { // Convert meters to tenths of a millimeter $mmx10 = $meters * 10000; // Divide by 9144 to get yards $y = intdiv($mmx10, 9144); // Use modulo division to get the remainder $f = $mmx10 % 9144; // Divide by 3048 to get feet $ft = intdiv($f, 3048); // Get the remainder and convert to inches $i = $f % 3048; $i = number_format($i / 254, 2); return "{$y} yards {$ft} feet {$i} inches"; }
/** * Calculate the median average of a list of numbers * * @param array $numbers * * @return number */ public static function median(array $numbers) { if (empty($numbers)) { return null; } // Reset the array key indexes because we don't know what might be passed in $numbers = array_values($numbers); // For odd number of numbers, take the middle indexed number if (count($numbers) % 2 == 1) { $middle_index = intdiv(count($numbers), 2); return self::kthSmallest($numbers, $middle_index); } // For even number of items, take the mean of the middle two indexed numbers $left_middle_index = intdiv(count($numbers), 2) - 1; $left_median = self::kthSmallest($numbers, $left_middle_index); $right_middle_index = $left_middle_index + 1; $right_median = self::kthSmallest($numbers, $right_middle_index); return self::mean([$left_median, $right_median]); }
<?php var_dump(intdiv(3, 2)); var_dump(intdiv(-3, 2)); var_dump(intdiv(3, -2)); var_dump(intdiv(-3, -2)); var_dump(intdiv(PHP_INT_MAX, PHP_INT_MAX)); var_dump(intdiv(-PHP_INT_MAX - 1, -PHP_INT_MAX - 1)); try { var_dump(intdiv(-PHP_INT_MAX - 1, -1)); } catch (Exception $e) { var_dump($e->getMessage()); } try { var_dump(intdiv(PHP_INT_MIN, -1)); } catch (Exception $e) { var_dump($e->getMessage()); } try { var_dump(intdiv(1, 0)); } catch (Exception $e) { var_dump($e->getMessage()); }
/** * Returns a copy of this Period with the years and months normalized. * * This normalizes the years and months units, leaving the days unit unchanged. * The months unit is adjusted to have an absolute value less than 12, * with the years unit being adjusted to compensate. For example, a period of * "1 year and 15 months" will be normalized to "2 years and 3 months". * * The sign of the years and months units will be the same after normalization. * For example, a period of "1 year and -25 months" will be normalized to * "-1 year and -1 month". * * @return Period */ public function normalized() { $totalMonths = $this->years * LocalTime::MONTHS_PER_YEAR + $this->months; $splitYears = intdiv($totalMonths, 12); $splitMonths = $totalMonths % 12; if ($splitYears === $this->years || $splitMonths === $this->months) { return $this; } return new Period($splitYears, $splitMonths, $this->days); }
/** * @expectedException DivisionByZeroError */ public function testIntdivByZero() { intdiv(1, 0); }
/** * Get (and increment) the nonce for AES-CTR * * @param int $increment * @return string */ protected function getNonce(int $increment = 0) : string { $nonce = ''; $ctr = $this->counter; while ($ctr > 0) { $nonce = \chr($ctr & 0xff) . $nonce; $ctr >>= 8; } $this->counter += intdiv($increment + $increment % 16, 16); return \str_pad($nonce, 16, "", STR_PAD_LEFT); }
/** * Used by all styles of Eve APIs to prepare and execute their SQL 'upsert' queries. * * 'Upsert' is a commonly used term for updating any existing rows in a table and inserting all the ones that don't * already exist together at one time. * * The method also tracks if the prepared query can be re-used or not to take fuller advantage of them in cases * where all queries have the same number of database rows as is common with some of the larger APIs and a few that * always have a fixed number of rows. * * @param string[] $columns * @param string[] $columnNames * @param string $tableName * * @return self Fluent interface. * @throws \DomainException * @throws \InvalidArgumentException * @throws \LogicException */ protected function flush(array $columns, array $columnNames, string $tableName) { if (0 === count($columns)) { return $this; } $rowCount = intdiv(count($columns), count($columnNames)); $mess = sprintf('Have %1$s row(s) to upsert into %2$s table', $rowCount, $tableName); $this->getYem()->triggerLogEvent('Yapeal.Log.log', Logger::INFO, $mess); $isNotPrepared = $this->lastColumnCount !== count($columnNames) || $this->lastRowCount !== $rowCount || null === $this->pdoStatement; if ($isNotPrepared) { $sql = $this->getCsq()->getUpsert($tableName, $columnNames, $rowCount); $mess = preg_replace('%(,\\([?,]*\\))+%', ',...', $sql); $lastError = preg_last_error(); if (PREG_NO_ERROR !== $lastError) { $constants = array_flip(get_defined_constants(true)['pcre']); $lastError = $constants[$lastError]; $mess = 'Received preg error ' . $lastError; throw new \DomainException($mess); } $this->getYem()->triggerLogEvent('Yapeal.Log.log', Logger::INFO, $mess); $this->pdoStatement = $this->getPdo()->prepare($sql); $this->lastColumnCount = count($columnNames); $this->lastRowCount = $rowCount; } $mess = ''; foreach ($columns as $column) { $mess .= $column . ','; if (256 <= strlen($mess)) { break; } } $mess = substr($mess, 0, 256) . '...'; $this->getYem()->triggerLogEvent('Yapeal.Log.log', Logger::DEBUG, $mess); $this->pdoStatement->execute($columns); return $this; }
/** * @expectedException ArithmeticError */ public function testSmallestNumber() { intdiv(~PHP_INT_MAX, -1); }
/** * Returns a copy of this LocalTime with the specified period in seconds added. * * @param integer $seconds The seconds to add, may be negative. * * @return LocalTime A LocalTime based on this time with the seconds added. */ public function plusSeconds($seconds) { $seconds = Cast::toInteger($seconds); if ($seconds === 0) { return $this; } $sofd = $this->hour * self::SECONDS_PER_HOUR + $this->minute * self::SECONDS_PER_MINUTE + $this->second; $newSofd = ($seconds % self::SECONDS_PER_DAY + $sofd + self::SECONDS_PER_DAY) % self::SECONDS_PER_DAY; if ($sofd === $newSofd) { return $this; } $hour = intdiv($newSofd, self::SECONDS_PER_HOUR); $minute = intdiv($newSofd, self::SECONDS_PER_MINUTE) % self::MINUTES_PER_HOUR; $second = $newSofd % self::SECONDS_PER_MINUTE; return new LocalTime($hour, $minute, $second, $this->nano); }
/** * @throws NegativeExponentException * @throws BaseIsZeroException * @param Integer $exp * @return Integer */ public function power(Integer $exp) : Integer { if ($exp->isNegative()) { throw new NegativeExponentException(); } if (0 == $this->value) { throw new BaseIsZeroException(); } $value = 1; $expValue = $exp->getValue(); $base = $this->value; while (0 < $expValue) { if ($expValue % 2 == 1) { $value *= $base; } $expValue = intdiv($expValue, 2); $base *= $base; // potential overflow } return new static($value); }
public function snoob(int $n) : int { if ($n === 0) { return $n; } $smallest = $n & -$n; $ripple = $n + $smallest; $ones = $n ^ $ripple; $ones = intdiv($ones >> 2, $smallest); return $ripple | $ones; }
public function __get(string $propertyName) { if ($propertyName === "length") { return intdiv($this->byteLength, static::BYTES_PER_ELEMENT); } else { return ArrayBufferView::__get($propertyName); } }
/** * Quartiles - Inclusive method (R method) * Three points that divide the data set into four equal groups, each group comprising a quarter of the data. * https://en.wikipedia.org/wiki/Quartile * * 0% is smallest number * Q1 (25%) is first quartile (lower quartile, 25th percentile) * Q2 (50%) is second quartile (median, 50th percentile) * Q3 (75%) is third quartile (upper quartile, 75th percentile) * 100% is largest number * interquartile_range is the difference between the upper and lower quartiles. (IQR = Q₃ - Q₁) * * Method used * - Use the median to divide the ordered data set into two halves. * - If there are an odd number of data points in the original ordered data set, * include the median (the central value in the ordered list) in both halves. * - If there are an even number of data points in the original ordered data set, * split this data set exactly in half. * - The lower quartile value is the median of the lower half of the data. * The upper quartile value is the median of the upper half of the data. * * The values found by this method are also known as "Tukey's hinges". * This is the method that the programming language R uses by default. * * @param array $numbers * @return array [ 0%, Q1, Q2, Q3, 100%, IQR ] */ public static function quartilesInclusive(array $numbers) : array { if (empty($numbers)) { return array(); } sort($numbers); $length = count($numbers); if ($length % 2 == 0) { $lower_half = array_slice($numbers, 0, $length / 2); $upper_half = array_slice($numbers, $length / 2); } else { $lower_half = array_slice($numbers, 0, intdiv($length, 2)); $upper_half = array_slice($numbers, intdiv($length, 2) + 1); // Add median to both halves $median = Average::median($numbers); array_push($lower_half, $median); array_unshift($upper_half, $median); } $lower_quartile = Average::median($lower_half); $upper_quartile = Average::median($upper_half); return ['0%' => min($numbers), 'Q1' => $lower_quartile, 'Q2' => Average::median($numbers), 'Q3' => $upper_quartile, '100%' => max($numbers), 'IQR' => $upper_quartile - $lower_quartile]; }
/** * Return the given subnet for an IPv6 address and mask bits * * @param string $ip * @param int $maskBits * @return string */ public function getIPv6Subnet(string $ip, int $maskBits = 48) : string { $binary = \inet_pton($ip); for ($i = 128; $i > $maskBits; $i -= 8) { $j = \intdiv($i, 8) - 1; $k = (int) \min(8, $i - $maskBits); $mask = 0xff - (2 ** $k - 1); $int = \unpack('C', $binary[$j]); $binary[$j] = \pack('C', $int[1] & $mask); } return \inet_ntop($binary) . '/' . $maskBits; }
/** * Returns the number of days since the UNIX epoch of 1st January 1970. * * @return integer */ public function toEpochDay() { $y = $this->year; $m = $this->month; $total = 365 * $y; if ($y >= 0) { $total += intdiv($y + 3, 4) - intdiv($y + 99, 100) + intdiv($y + 399, 400); } else { $total -= intdiv($y, -4) - intdiv($y, -100) + intdiv($y, -400); } $total += intdiv(367 * $m - 362, 12); $total += $this->day - 1; if ($m > 2) { $total--; if (!$this->isLeapYear()) { $total--; } } return $total - self::DAYS_0000_TO_1970; }
/** * Pager section * * @param array $§ * * @return string */ function section_pager(array &$§) : string { $§['vars'] += ['size' => 0, 'limit' => 0, 'links' => [], 'params' => []]; if ($§['vars']['size'] < 1 || $§['vars']['limit'] < 1) { return ''; } $§['vars']['pages'] = (int) ceil($§['vars']['size'] / $§['vars']['limit']); $§['vars']['page'] = max($§['vars']['params']['page'] ?? 0, 1); $§['vars']['offset'] = ($§['vars']['page'] - 1) * $§['vars']['limit']; unset($§['vars']['params']['page']); $c = max(0, data('limit', 'pager')); $min = max(1, min($§['vars']['page'] - intdiv($c, 2), $§['vars']['pages'] - $c + 1)); $max = min($min + $c - 1, $§['vars']['pages']); if ($§['vars']['page'] >= 2) { $p = $§['vars']['page'] === 2 ? $§['vars']['params'] : ['page' => $§['vars']['page'] - 1] + $§['vars']['params']; $§['vars']['links'][] = ['name' => _('Previous'), 'params' => $p]; } for ($i = $min; $min < $max && $i <= $max; $i++) { $p = $i > 1 ? ['page' => $i] + $§['vars']['params'] : $§['vars']['params']; $§['vars']['links'][] = ['name' => $i, 'params' => $p, 'active' => $i === $§['vars']['page']]; } if ($§['vars']['page'] < $§['vars']['pages']) { $p = ['page' => $§['vars']['page'] + 1] + $§['vars']['params']; $§['vars']['links'][] = ['name' => _('Next'), 'params' => $p]; } return render($§); }
<?php var_dump(intdiv(100, 3)); //33 返回100的整数倍数
<?php // (int)(PHP_INT_MAX / 3) gives a different result var_dump(intdiv(PHP_INT_MAX, 3));
/** * Get the value within a group (i.e. 1.0.3 => 1000300) * * @param int $value An expanded version * @param int $group * @return int */ public static function getGroup(int $value, int $group = self::GROUP_INCREMENT) : int { switch ($group) { // [W...W]XXYYZZ case self::GROUP_MAJOR: $left = $value - $value % self::GROUP_MAJOR; return intdiv($left, self::GROUP_MAJOR); // W...W[XX]YYZZ // W...W[XX]YYZZ case self::GROUP_MINOR: $left = $value - $value % self::GROUP_MINOR; $left %= self::GROUP_MAJOR; return intdiv($left, self::GROUP_MINOR); // W...WXX[YY]ZZ // W...WXX[YY]ZZ case self::GROUP_PATCH: $left = $value - $value % self::GROUP_PATCH; $left %= self::GROUP_MINOR; return intdiv($left, self::GROUP_PATCH); default: throw new \InvalidArgumentException(\__('%s: $group must be a constant', 'default', __METHOD__)); } }
<?php // Convert $total_minutes to hours and minutes. $total_minutes = 640; $minutes = $total_minutes % 60; //$hours = ($total_minutes - $minutes) / 60; $hours = intdiv($total_minutes, 60); echo "Time taken was {$hours} hours {$minutes} minutes";
/** * This method returns the result of dividing the specified value against this object's * value. * * @access public * @static * @param IInt32\Type $x the left operand * @param IInt32\Type $y the right operand * @return IInt32\Type the result */ public static function divide(IInt32\Type $x, IInt32\Type $y) : IInt32\Type { return IInt32\Type::box(intdiv($x->unbox(), $y->unbox())); }
/** * Returns a copy of this `LocalDateTime` with the specified period added. * * @param integer $hours The hours to add, validated as an integer. May be negative. * @param integer $minutes The minutes to add, validated as an integer. May be negative. * @param integer $seconds The seconds to add, validated as an integer. May be negative. * @param integer $nanos The nanos to add, validated as an integer. May be negative. * @param integer $sign The sign, validated as an integer of value `1` to add or `-1` to subtract. * * @return LocalDateTime The combined result. */ private function plusWithOverflow($hours, $minutes, $seconds, $nanos, $sign) { $totDays = intdiv($hours, LocalTime::HOURS_PER_DAY) + intdiv($minutes, LocalTime::MINUTES_PER_DAY) + intdiv($seconds, LocalTime::SECONDS_PER_DAY); $totDays *= $sign; $totSeconds = $seconds % LocalTime::SECONDS_PER_DAY + $minutes % LocalTime::MINUTES_PER_DAY * LocalTime::SECONDS_PER_MINUTE + $hours % LocalTime::HOURS_PER_DAY * LocalTime::SECONDS_PER_HOUR; $curSoD = $this->time->toSecondOfDay(); $totSeconds = $totSeconds * $sign + $curSoD; $totNanos = $nanos * $sign + $this->time->getNano(); $totSeconds += Math::floorDiv($totNanos, LocalTime::NANOS_PER_SECOND); $newNano = Math::floorMod($totNanos, LocalTime::NANOS_PER_SECOND); $totDays += Math::floorDiv($totSeconds, LocalTime::SECONDS_PER_DAY); $newSoD = Math::floorMod($totSeconds, LocalTime::SECONDS_PER_DAY); $newTime = $newSoD === $curSoD ? $this->time : LocalTime::ofSecondOfDay($newSoD, $newNano); return $this->with($this->date->plusDays($totDays), $newTime); }
/** * Write the data to file name using randomized tmp file, exclusive locking, and time limits. * * Things that can cause write to fail: * * * Unable to acquire exclusive file handle within calculated time or tries limits. * * Write stalls without making any progress or repeatedly stalls to often. * * Exceeds estimated write time based on file size with 2 second minimum enforced. * * @param string $pathFile File name with absolute path. * * @param string $data Contents to be written to file. * * @return bool Returns true if contents written, false on any problem that prevents write. */ private function safeDataWrite(string $pathFile, string $data) : bool { $amountToWrite = strlen($data); // Buffer size between 4KB and 256KB with 16MB file size uses a 100KB buffer. $bufferSize = (int) (1 + floor(log($amountToWrite, 2))) << 12; // Write timeout calculated by using file size and write speed of // 16MB/sec with 2 second minimum time enforced. $timeout = max(2, intdiv($amountToWrite, 1 << 24)); $handle = $this->acquireLockedHandle($pathFile, $timeout); if (false === $handle) { return false; } $dataWritten = 0; $tries = 0; $timeout = time() + $timeout; while ($dataWritten < $amountToWrite) { if (++$tries > 10 || time() > $timeout) { $this->releaseHandle($handle); $this->deleteWithRetry($pathFile); return false; } $written = fwrite($handle, substr($data, $dataWritten, $bufferSize)); // Decrease $tries while making progress but NEVER $tries <= 0. if ($written > 0 && $tries > 0) { --$tries; } $dataWritten += $written; } $this->releaseHandle($handle); return true; }