For example, since 25 and 2.2360679775 (or 5^0.5) are both powers of 5, I want the function to return 5.
The only way I've found is to brute force it and just try every number.
$one=25;
$two=125;
for($b=2;$b<=10;$b++)
{
$x=pow($one,1/$b);
for($c=2;$c<=10;$c++)
{
$y=pow($two,1/$c);
if($y == $x)
{
return $x;
}
}
}
As Mbo points out in the comments, every number (z) is the power some number (x) to some other number (y). So, it's not entirely clear what you mean when you say, 'if two numbers are numbers of the same power'. Notwithstanding, you can easily (without using brute force) find y given x and z, using the log() function in php, like so:
$z=125;
$x=5;
$y=log($z, $x);
print $z . ' is ' . $x . ' to the power of ' . $y . '.';
This should produce:
125 is 5 to the power of 3.
Related
How does one generate a random float between 0 and 1 in PHP?
I'm looking for the PHP's equivalent to Java's Math.random().
You may use the standard function: lcg_value().
Here's another function given on the rand() docs:
// auxiliary function
// returns random number with flat distribution from 0 to 1
function random_0_1()
{
return (float)rand() / (float)getrandmax();
}
Example from documentation :
function random_float ($min,$max) {
return ($min+lcg_value()*(abs($max-$min)));
}
rand(0,1000)/1000 returns:
0.348 0.716 0.251 0.459 0.893 0.867 0.058 0.955 0.644 0.246 0.292
or use a bigger number if you want more digits after decimal point
class SomeHelper
{
/**
* Generate random float number.
*
* #param float|int $min
* #param float|int $max
* #return float
*/
public static function rand($min = 0, $max = 1)
{
return ($min + ($max - $min) * (mt_rand() / mt_getrandmax()));
}
}
update:
forget this answer it doesnt work wit php -v > 5.3
What about
floatVal('0.'.rand(1, 9));
?
this works perfect for me, and it´s not only for 0 - 1 for example between 1.0 - 15.0
floatVal(rand(1, 15).'.'.rand(1, 9));
function mt_rand_float($min, $max, $countZero = '0') {
$countZero = +('1'.$countZero);
$min = floor($min*$countZero);
$max = floor($max*$countZero);
$rand = mt_rand($min, $max) / $countZero;
return $rand;
}
example:
echo mt_rand_float(0, 1);
result: 0.2
echo mt_rand_float(3.2, 3.23, '000');
result: 3.219
echo mt_rand_float(1, 5, '00');
result: 4.52
echo mt_rand_float(0.56789, 1, '00');
result: 0.69
$random_number = rand(1,10).".".rand(1,9);
function frand($min, $max, $decimals = 0) {
$scale = pow(10, $decimals);
return mt_rand($min * $scale, $max * $scale) / $scale;
}
echo "frand(0, 10, 2) = " . frand(0, 10, 2) . "\n";
This question asks for a value from 0 to 1. For most mathematical purposes this is usually invalid albeit to the smallest possible degree. The standard distribution by convention is 0 >= N < 1. You should consider if you really want something inclusive of 1.
Many things that do this absent minded have a one in a couple billion result of an anomalous result. This becomes obvious if you think about performing the operation backwards.
(int)(random_float() * 10) would return a value from 0 to 9 with an equal chance of each value. If in one in a billion times it can return 1 then very rarely it will return 10 instead.
Some people would fix this after the fact (to decide that 10 should be 9). Multiplying it by 2 should give around a ~50% chance of 0 or 1 but will also have a ~0.000000000465% chance of returning a 2 like in Bender's dream.
Saying 0 to 1 as a float might be a bit like mistakenly saying 0 to 10 instead of 0 to 9 as ints when you want ten values starting at zero. In this case because of the broad range of possible float values then it's more like accidentally saying 0 to 1000000000 instead of 0 to 999999999.
With 64bit it's exceedingly rare to overflow but in this case some random functions are 32bit internally so it's not no implausible for that one in two and a half billion chance to occur.
The standard solutions would instead want to be like this:
mt_rand() / (getrandmax() + 1)
There can also be small usually insignificant differences in distribution, for example between 0 to 9 then you might find 0 is slightly more likely than 9 due to precision but this will typically be in the billionth or so and is not as severe as the above issue because the above issue can produce an invalid unexpected out of bounds figure for a calculation that would otherwise be flawless.
Java's Math.random will also never produce a value of 1. Some of this comes from that it is a mouthful to explain specifically what it does. It returns a value from 0 to less than one. It's Zeno's arrow, it never reaches 1. This isn't something someone would conventionally say. Instead people tend to say between 0 and 1 or from 0 to 1 but those are false.
This is somewhat a source of amusement in bug reports. For example, any PHP code using lcg_value without consideration for this may glitch approximately one in a couple billion times if it holds true to its documentation but that makes it painfully difficult to faithfully reproduce.
This kind of off by one error is one of the common sources of "Just turn it off and on again." issues typically encountered in embedded devices.
Solution for PHP 7. Generates random number in [0,1). i.e. includes 0 and excludes 1.
function random_float() {
return random_int(0, 2**53-1) / (2**53);
}
Thanks to Nommyde in the comments for pointing out my bug.
>>> number_format((2**53-1)/2**53,100)
=> "0.9999999999999998889776975374843459576368331909179687500000000000000000000000000000000000000000000000"
>>> number_format((2**53)/(2**53+1),100)
=> "1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
Most answers are using mt_rand. However, mt_getrandmax() usually returns only 2147483647. That means you only have 31 bits of information, while a double has a mantissa with 52 bits, which means there is a density of at least 2^53 for the numbers between 0 and 1.
This more complicated approach will get you a finer distribution:
function rand_754_01() {
// Generate 64 random bits (8 bytes)
$entropy = openssl_random_pseudo_bytes(8);
// Create a string of 12 '0' bits and 52 '1' bits.
$x = 0x000FFFFFFFFFFFFF;
$first12 = pack("Q", $x);
// Set the first 12 bits to 0 in the random string.
$y = $entropy & $first12;
// Now set the first 12 bits to be 0[exponent], where exponent is randomly chosen between 1 and 1022.
// Here $e has a probability of 0.5 to be 1022, 0.25 to be 1021, etc.
$e = 1022;
while($e > 1) {
if(mt_rand(0,1) == 0) {
break;
} else {
--$e;
}
}
// Pack the exponent properly (add four '0' bits behind it and 49 more in front)
$z = "\0\0\0\0\0\0" . pack("S", $e << 4);
// Now convert to a double.
return unpack("d", $y | $z)[1];
}
Please note that the above code only works on 64-bit machines with a Litte-Endian byte order and Intel-style IEEE754 representation. (x64-compatible computers will have this). Unfortunately PHP does not allow bit-shifting past int32-sized boundaries, so you have to write a separate function for Big-Endian.
You should replace this line:
$z = "\0\0\0\0\0\0" . pack("S", $e << 4);
with its big-endian counterpart:
$z = pack("S", $e << 4) . "\0\0\0\0\0\0";
The difference is only notable when the function is called a large amount of times: 10^9 or more.
Testing if this works
It should be obvious that the mantissa follows a nice uniform distribution approximation, but it's less obvious that a sum of a large amount of such distributions (each with cumulatively halved chance and amplitude) is uniform.
Running:
function randomNumbers() {
$f = 0.0;
for($i = 0; $i < 1000000; ++$i) {
$f += \math::rand_754_01();
}
echo $f / 1000000;
}
Produces an output of 0.49999928273099 (or a similar number close to 0.5).
I found the answer on PHP.net
<?php
function randomFloat($min = 0, $max = 1) {
return $min + mt_rand() / mt_getrandmax() * ($max - $min);
}
var_dump(randomFloat());
var_dump(randomFloat(2, 20));
?>
float(0.91601131712832)
float(16.511210331931)
So you could do
randomFloat(0,1);
or simple
mt_rand() / mt_getrandmax() * 1;
what about:
echo (float)('0.' . rand(0,99999));
would probably work fine... hope it helps you.
I am having a variety of long numbers and I am trying to write a function to format them correctly. Can someone help me out?
I already tried "number_format()" and "round()" but that doesn't solve my problems..
I would like to round it like following:
1024.43 --> 1,024.43
0.000000931540 --> 0.000000932
0.003991 --> 0.00399
0.3241 --> 0.324
1045.3491 --> 1,045.35
So that means, If number is bigger than "0" it should round to 2 decimal places and add thousands seperator (like 6,554.24) AND if number less than "1" it should round to 3 digits whenever numbers appear after the zeros (for example 0.0003219 to 0.000322 OR 0.2319 to 0.232)
EDIT:
The same should apply to "-" values. For example:
-1024.43 --> -1,024.43
-0.000000931540 --> -0.000000932
-0.003991 --> -0.00399
-0.3241 --> -0.324
-1045.3491 --> -1,045.35
Adapting from https://stackoverflow.com/a/48283297/2469308
handle this in two separate cases.
for numbers between -1 and 1; we need to calculate the number of digits to round. And then, using number_format() function we can get the result.
for else, simply use number_format() function with decimal digits set to 2.
Try the following:
function customRound($value)
{
if ($value > -1 && $value < 1) {
// define the number of significant digits needed
$digits = 3;
if ($value >= 0) {
// calculate the number of decimal places to round to
$decimalPlaces = $digits - floor(log10($value)) - 1;
} else {
$decimalPlaces = $digits - floor(log10($value * -1)) - 1;
}
// return the rounded value
return number_format($value, $decimalPlaces);
} else {
// simply use number_format function to show upto 2 decimal places
return number_format($value, 2);
}
// for the rest of the cases - return the number simply
return $value;
}
Rextester DEMO
$x = 123.456;
echo number_format($x, max(2, 3 - ceil(log10(abs($x))))) . "\n";
$x = 1.23456;
echo number_format($x, max(2, 3 - ceil(log10(abs($x))))) . "\n";
$x = 0.0123456;
echo number_format($x, max(2, 3 - ceil(log10(abs($x))))) . "\n";
$x = 0.0000123456;
echo number_format($x, max(2, 3 - ceil(log10(abs($x))))) . "\n";
$x = 0.000000123456;
echo number_format($x, max(2, 3 - ceil(log10(abs($x))))) . "\n";
$x = 0.00000000123456;
echo number_format($x, max(2, 3 - ceil(log10(abs($x))))) . "\n";
Output:
123.45
1.23
0.0123
0.0000123
0.000000123
0.00000000123
Basically this always keeps a minimal of 2 decimal digits up to 3 significant digits.
However, because of the way floating point is handled internally (as power of 2 and not 10), there are some catches. Numbers like 0.1 and 0.001 and so forth can't be stored precisely, so they are actually stored as 0.09999999... or things like that. In cases like this it may seem like it is computing things wrong and give you answers with more significant digits than it should.
You can try to counteract this phenomena by allowing an error margin to the formula:
number_format($x, max(2, 3 - ceil(log10(abs($x))) - 1e-8))
But this may cause other undesirable effects. You will have to make tests.
At some point i had this block of code:
while( $i> $l-1 )
{
$x= fmod($i,$l);
$i= floor($i/$l);
}
I decided to get rid of the modulo operation and wrote this block:
while( true )
{
$d= floor( $i/$l );
if( $d>= 1 )
{
$x= $i - ($d*$l);
$i= $d;
}
else
{
break;
}
}
The $x is used for indexing an array of length $l. The $i is in question here.
While for some relatively small initial $i, both blocks give the same $x over all iterations, when initialized with something close to PHP_INT_MAX the two blocks do not give the same $x.
Unfortunately $l cannot become a power of 2 in order to use bit operators so i am stuck with this.
I am guessing it has something to do with the inner roundings that take place. Could fmod be so optimized for this case? Is there something i am not seeing?
Additional Comment after accepting #trincot 's answer.
One thing i should have mentioned is that although one would expect the second method to produce better results, due to using simple subtraction, it did not. Possibly because of the division taking place at the beginning of the loop.(that is why i asked "Could fmod be so optimized).
According to the documentation, fmod works on floats:
fmod — Returns the floating point remainder (modulo) of the division of the arguments
Instead, the modulo operator (%) would be more suitable for what you need:
Operands of modulus are converted to integers (by stripping the decimal part) before processing.
fmod will become inaccurate for large integers as the floating point representation does not have the same precision.
Examples of some oddities that happen:
$l=3;
$i=9223372036854775295;
echo is_int($i) . "<br>"; // 1 (true)
echo (9223372036854775295==$i) . "<br>"; // 1 (true)
echo number_format($i, 0, ".", "") . "<br>"; // 9223372036854774784
echo fmod($i,$l) . "<br>"; // 1
echo fmod($i-1,$l) . "<br>"; // 1
echo fmod($i-2,$l) . "<br>"; // 1
echo ($i % $l) . "<br>"; // 2
echo (($i-1) % $l) . "<br>"; // 1
echo (($i-2) % $l) . "<br>"; // 0
Notice how a simple number_format already destroys the precision of the integer; it returns a different number because of floating point conversion.
Notice also that this lack of precision makes fmod return 1 for three consecutive numbers, while the modulo operator does what you would want.
So you seem much better of with %.
Alternative
Your function seems to break down a number into its "digits" in an L-basis. For instance, when $l=2, your $x-sequence produces the binary representation of the number, except for the last digit which you leave out.
In that respect, you might have a look at the function call base_convert($i,10,$l), which produces one digit corresponding to a value of $x in your code, with letters for digits above 9. The function can accept $l values up to 36.
In my database I have a store of property values in Int form. They range from $1000 to $100,000,000. How would I create a function that could break this information down to symbolized text/decimal form.
For example
1,300,000 would become 1.3 Million
250,000 would become 250 Thousand
10,300,000 would become 10.3 Million
What I'm trying to get is the English equivalent of the long number
Any Idea on where to start?
I used something similar to this once:
function abbNumber($var)
{
if(($var/1000000000)>1)
{
$retVal=round($var/1000000000,1).' hundred million';
}
else if(($var/1000000)>1)
{
$retVal=round($var/1000000,1).' million';
}
else if(($var/1000)>1)
{
$retVal=round($var/1000,1).' thousand';
}
else
{
$retVal=$var;
}
return $retVal;
}
echo abbNumber(5234000);
?>
// 5.2 million
echo abbNumber(5234000000);
5.2 hundred million
echo abbNumber(523400000);
523.4 million
echo abbNumber(523400);
523.4 thousand
echo abbNumber(5.234);
5.234
Start here:
$x = 1300000;
$text = ($x / 1000000) . ' Million';
Then, detect the number of digits in your source number to check whether it makes more sense to divide by thousand or a million.
Then, apart from dividing, also round the number, so 1,387,238 is translated to 1.4 Million instead of 1.387238 Million.
I have two numbers which are supposed to be equal to return a difference, I doesn't make sense...
The only way to be able to reproduce this problem here I had to base64_encode my arrays,
here is the script:
basically the script will fix numbers like "1 234,5" to "1234.5" and does calculations, but at the ends it returns
First Number: 4784.47
Second Number: 4784.47
Difference: 9.0949470177293E-13
I just don't understand????????
$aa = 'YTo3OntpOjA7YToxMDp7czoxMToiRGVzY3JpcHRpb24iO3M6MTI6IkvDqWsgc3rDoW1vayI7czo2OiJQZXJpb2QiO3M6MTI6IjA4LjEwLTA4LjEwLiI7czo2OiJBbW91bnQiO3M6MToiMSI7czoxMjoiRHVyYXRpb25UaW1lIjtzOjc6IjA6MDQ6MDAiO3M6MTI6Ik5ldFVuaXRQcmljZSI7czo1OiIzNSwyMCI7czo5OiJOZXRBbW91bnQiO3M6NjoiMTQwLDgwIjtzOjEwOiJWQVRQZXJjZW50IjtzOjM6IjI1JSI7czozOiJWQVQiO3M6NToiMzUsMjAiO3M6MTE6Ikdyb3NzQW1vdW50IjtzOjY6IjE3NiwwMCI7czo4OiJJdGVtQ29kZSI7czo0OiJCTFVFIjt9aToxO2E6MTA6e3M6MTE6IkRlc2NyaXB0aW9uIjtzOjE3OiJCZWxmw7ZsZGkgaMOtdsOhcyI7czo2OiJQZXJpb2QiO3M6MTI6IjA3LjIyLTA4LjExLiI7czo2OiJBbW91bnQiO3M6MjoiMTIiO3M6MTI6IkR1cmF0aW9uVGltZSI7czo3OiIwOjIxOjQzIjtzOjEyOiJOZXRVbml0UHJpY2UiO3M6NToiMTUsMjAiO3M6OToiTmV0QW1vdW50IjtzOjY6IjMzMCwxMCI7czoxMDoiVkFUUGVyY2VudCI7czozOiIyNSUiO3M6MzoiVkFUIjtzOjU6IjgyLDUyIjtzOjExOiJHcm9zc0Ftb3VudCI7czo2OiI0MTIsNjIiO3M6ODoiSXRlbUNvZGUiO3M6ODoiRklYX0ZMQVQiO31pOjI7YToxMDp7czoxMToiRGVzY3JpcHRpb24iO3M6MjM6IkVnecOpYiBtb2JpbCBlZ3lzw6lnw6FyIjtzOjY6IlBlcmlvZCI7czoxMjoiMDcuMjEtMDguMTEuIjtzOjY6IkFtb3VudCI7czoyOiI1MCI7czoxMjoiRHVyYXRpb25UaW1lIjtzOjc6IjE6MDE6MzgiO3M6MTI6Ik5ldFVuaXRQcmljZSI7czo1OiIxNSwyMCI7czo5OiJOZXRBbW91bnQiO3M6NjoiOTM2LDgzIjtzOjEwOiJWQVRQZXJjZW50IjtzOjM6IjI1JSI7czozOiJWQVQiO3M6NjoiMjM0LDIxIjtzOjExOiJHcm9zc0Ftb3VudCI7czo4OiIxIDE3MSwwNCI7czo4OiJJdGVtQ29kZSI7czo4OiJPRkZfRkxBVCI7fWk6MzthOjEwOntzOjExOiJEZXNjcmlwdGlvbiI7czoxOToiVm9kYWZvbmUgZWd5c8OpZ8OhciI7czo2OiJQZXJpb2QiO3M6MTI6IjA3LjE1LTA4LjEyLiI7czo2OiJBbW91bnQiO3M6MjoiMjAiO3M6MTI6IkR1cmF0aW9uVGltZSI7czo3OiIwOjU0OjM3IjtzOjEyOiJOZXRVbml0UHJpY2UiO3M6NToiMTUsMjAiO3M6OToiTmV0QW1vdW50IjtzOjY6Ijc2MywwNSI7czoxMDoiVkFUUGVyY2VudCI7czozOiIyNSUiO3M6MzoiVkFUIjtzOjY6IjE5MCw3NiI7czoxMToiR3Jvc3NBbW91bnQiO3M6NjoiOTUzLDgxIjtzOjg6Ikl0ZW1Db2RlIjtzOjc6Ik9OX0ZMQVQiO31pOjQ7YToxMDp7czoxMToiRGVzY3JpcHRpb24iO3M6MTU6Ik5lbXpldGvDtnppIFNNUyI7czo2OiJQZXJpb2QiO3M6MTI6IjA3LjEzLTA4LjEzLiI7czo2OiJBbW91bnQiO3M6MjoiNDIiO3M6MTI6IkR1cmF0aW9uVGltZSI7czoxOiItIjtzOjEyOiJOZXRVbml0UHJpY2UiO3M6NToiMzAsNDAiO3M6OToiTmV0QW1vdW50IjtzOjg6IjEgMjc2LDgwIjtzOjEwOiJWQVRQZXJjZW50IjtzOjM6IjI1JSI7czozOiJWQVQiO3M6NjoiMzE5LDIwIjtzOjExOiJHcm9zc0Ftb3VudCI7czo4OiIxIDU5NiwwMCI7czo4OiJJdGVtQ29kZSI7czo3OiJTTVNfSU5UIjt9aTo1O2E6MTA6e3M6MTE6IkRlc2NyaXB0aW9uIjtzOjIzOiJTTVMgaMOhbMOzemF0b24ga8OtdsO8bCI7czo2OiJQZXJpb2QiO3M6MTI6IjA3LjI1LTA4LjExLiI7czo2OiJBbW91bnQiO3M6MjoiMTUiO3M6MTI6IkR1cmF0aW9uVGltZSI7czoxOiItIjtzOjEyOiJOZXRVbml0UHJpY2UiO3M6NToiMTUsMjAiO3M6OToiTmV0QW1vdW50IjtzOjY6IjIyOCwwMCI7czoxMDoiVkFUUGVyY2VudCI7czozOiIyNSUiO3M6MzoiVkFUIjtzOjU6IjU3LDAwIjtzOjExOiJHcm9zc0Ftb3VudCI7czo2OiIyODUsMDAiO3M6ODoiSXRlbUNvZGUiO3M6NzoiU01TX09GRiI7fWk6NjthOjEwOntzOjExOiJEZXNjcmlwdGlvbiI7czoyMjoiU01TIGjDoWzDs3phdG9uIGJlbMO8bCI7czo2OiJQZXJpb2QiO3M6MTI6IjA3LjE3LTA4LjEyLiI7czo2OiJBbW91bnQiO3M6MjoiMTUiO3M6MTI6IkR1cmF0aW9uVGltZSI7czoxOiItIjtzOjEyOiJOZXRVbml0UHJpY2UiO3M6NToiMTUsMjAiO3M6OToiTmV0QW1vdW50IjtzOjY6IjE1MiwwMCI7czoxMDoiVkFUUGVyY2VudCI7czozOiIyNSUiO3M6MzoiVkFUIjtzOjU6IjM4LDAwIjtzOjExOiJHcm9zc0Ftb3VudCI7czo2OiIxOTAsMDAiO3M6ODoiSXRlbUNvZGUiO3M6NjoiU01TX09OIjt9fQ==';
$tt = 'YTozOntzOjE2OiJTdW1tYXJ5SXRlbU5ldHRvIjtzOjg6IjMgODI3LDU4IjtzOjE0OiJTdW1tYXJ5SXRlbVZBVCI7czo2OiI5NTYsODkiO3M6MTc6IlN1bW1hcnlJdGVtQnJ1dHRvIjtzOjg6IjQgNzg0LDQ3Ijt9';
$a = unserialize(base64_decode($aa));
$t = unserialize(base64_decode($tt));
function calculate_call_fees($a,$t){
$or_item = 0;
foreach($a as $k => $r) {
$or_item += fix_num($r['GrossAmount']);
}
$br = fix_num($t['SummaryItemBrutto']);
if($br>$or_item){
$diff = $br-$or_item;
} else {
$diff = 0;
}
echo 'First Number: ' . $br.'<br/>';
echo 'Second Number: ' . $or_item.'<br />';
echo 'Difference: ' . $diff.'<br />';
echo '<hr />';
echo '<pre>';
print_r($a);
echo '</pre>';
echo '<hr />';
echo '<pre>';
print_r($t);
echo '</pre>';
}
function fix_num($n){
return floatval(str_replace(Array(" ",","),array("","."),$n));
}
calculate_call_fees($a,$t);
Using "equals" comparison with floating point numbers is dangerous because of floating point limited precision - you're liable to get small differences due to the rounding involved.
Instead, if you want to see if two floating point numbers are "the same", just see if their difference is below a certain threshold:
if( abs($a - $b) < 0.00000001) {
// a and b are "equal"
}
It is not just PHP. There is a general problem of representing fractional numbers in the computer. It's subject for various types of overflows, underflows, precision issues and so on. PHP's manual shed some light on the topic.
The general rule - if you demand for two 'seem-equal' numbers to be guaranteed equal - don't use floating point data types (float, double), but fixed point (decimal, numeric)
It appears as this is "Machine epsilon" issue:
http://en.wikipedia.org/wiki/Machine_epsilon
Try to compare the difference between them with 0.000001 instead of comparing them directly.