I am trying to calculate in PHP. When I try to do that I can see that the result is mostly wrong.
The script I am using is the following:
$newrate = 1 / $rate["rate"];
echo '1 /'. $rate["rate"]. ' = '.$newrate;
The result I get is the following:
1 /1.0867 = 1
1 /117.01 = 0.0085470085470085
1 /1.9558 = 1
1 /27.534 = 0.037037037037037
1 /7.4589 = 0.14285714285714
1 /1.0867 should be 0.92021717125 and not 1.
I can reproduce this step by adding the following line to my script:
$rate["rate"] = 1.0867;
When I run the script the result is still 1. When I change my script like:
$newrate = 1 / 1.0867;
echo '1 / 1.0867 = '.$newrate;
I get a correct result. The output is then: 0.92021717125.
Does someone know what is wrong with this script? What is the reason that my script is making incorrect calculations?
Update 1:
Here is my full script:
<?php
$XML=simplexml_load_file("https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml");
foreach($XML->Cube->Cube as $rat)
{
foreach($rat as $rate)
{
$newrate = '1' / $rate["rate"];
echo '1 /' . $rate["rate"] . ' = ' . $newrate;
echo '<br /><br />';
}
}
?>
I think there is something wrong with your example. I tested exactly what you described and works as expected.
<?php
$rate = [];
$rate["rate"] = "1.0867";
$newrate = 1 / $rate["rate"];
echo '1 / ' . $rate["rate"] . ' = ' . $newrate;
// 1 / 1.0867 = 0.92021717125242
You can see it running here
https://repl.it/#thiagodamata/NeighboringPeachpuffArchitect
Probably, you are using "," instead of "." when sending the number.
PHP cast the number only until it hits something unexpected. So "1,0867" is cast to 1. It is a classic problem when dealing with numbers in different formats, considering different languages.
<?php
// simulating the "," error
$rate["rate"] = "1,0867";
$newrate = 1 / $rate["rate"];
echo '1 / ' . $rate["rate"] . ' = ' . $newrate;
// 1 / 1,0867 = 1
Take a look in this thread about how to cast the number from different languages masks PHP: Locale aware number format and take a deeper look into the PHP function number-format https://www.php.net/manual/en/function.number_format.php
Update - After getting the full code example
Looking to your full code becomes more clear the problem. The var that you are getting in the loop it is a SimpleXmlElement, not a string. So, SimpleXmlElement is printed as the "1.0867" but it is not its real value.
To make the SimpleXmlElement cast to float properly, you need to use the cast function.
<?php
$XML=simplexml_load_file("https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml");
foreach($XML->Cube->Cube as $rat)
{
foreach($rat as $rate)
{
print(var_dump($rate["rate"]));
/*
object(SimpleXMLElement)#7 (1) {
[0]=>
string(6) "1.0867"
}
*/
print("class = [" . get_class($rate["rate"]) . "]\n");
// class = [SimpleXMLElement]
print("as string = [" . $rate["rate"] . "]\n");
// as string = [1.0867]
print("without cast = [" . (1 * $rate["rate"]) . "]\n");
// without cast = [1]
$a = (float)($rate["rate"]);
print("with cast = [" . ($a) . "]\n");
// with cast = [1.0867]
print(serialize($a));
//d:1.0867;
$newrate = '1' / $a;
echo '1 / ' . $a . ' = ' . $newrate . "\n";
// 1 / 1.0867 = 0.92021717125242
echo '<br /><br />';
exit();
}
}
?>
You can see this running here:
https://repl.it/#thiagodamata/FuchsiaLightheartedPrintablecharacter
Just printing the value of a var does not always give you the real value of some object. There are other functions like var_export https://www.php.net/manual/en/function.var-export.php, var_dump https://www.php.net/manual/en/function.var-dump.php and serialize that may help you to see the real value of the vars.
Calculations are fine, and correct
You've not taken into account implicit type casting in PHP. Try this:
<?php
print "integer divided by float = " . (1 /1.0867) . "\n"; // returns 0.9202171712524
print "Integer divided by string = " . ((1/"1.0867") . "\n"; // returns 1
You are expecting PHP to know what your intention is when you throw a tring into an arithmetic operation - that's not how PHP works.
Just because it is dynamically typed doesn't mean you don't need to be careful with your data types.
print (1/(float)$rate['rate'];
try cast all values as a float
echo 1.0 / (float) $rate['rate'];
Related
Im trying to get out an average value from a vote function.
<?php
$file = file("textfile.txt");
$textfil = file_get_contents("textfile.txt");
$textfill = str_split($textfil);
echo "Number of votes: " . count($textfill) . "<br>";
$sum = 0;
foreach ($textfill as $vote) {
$sum = $sum + intval($vote);
}
echo "Average: " . $sum;
?>
Simple by substitute (+) with a (/), and even tried a (%). But still getting error message.
Would appreciate alot if anyone could help me out and tell me what im doing wrong.
/thanks
Edit
Sidenote: Please read an explanation under "First answer given" further down below.
This version will take into account any blank lines in a file, if the content looks like:
1
2
3
// <- blank line
Sidenote: Please provide a sample of your text file. A comment has already been given to that effect.
PHP
<?php
// first line not required
// $file = file("textfile.txt");
$textfil = file_get_contents("textfile.txt");
$textfill = array_filter(array_map("trim", file("textfile.txt")), "strlen");
echo "Number of votes: " . count($textfill) . "<br>";
$sum = 0;
foreach ($textfill as $vote) {
$sum += intval($vote);
}
$avg = $sum / count($textfill);
echo "Average: " . $avg;
?>
First answer given
Using the following in a text file: (since no example of file content was given)
5
5
5
IMPORTANT NOTE: There should not be a carriage return after the last entry.
produced
Number of votes: 5
Average: 3
which is false, since there are 3 entries in the text file.
explode() should be used, and not str_split()
The following using the same text file produced:
Number of votes: 3
Average: 5
which is correct. In simple mathematics, averages are done by adding all numbers then dividing them by how many numbers there are.
In this case it's 3 numbers (all 5's) added equals 15, divided by 3 is 5.
Sidenote: The first line is not required $file = file("textfile2.txt");
<?php
// first line not required
// $file = file("textfile.txt");
$textfil = file_get_contents("textfile.txt");
$textfill = explode("\n", $textfil);
echo "Number of votes: " . count($textfill) . "<br>";
$sum = 0;
foreach ($textfill as $vote) {
$sum += intval($vote);
}
$avg = $sum / count($textfill);
echo "Average: " . $avg;
?>
Footnotes:
If the average comes out to 8.33333 and you would like it to be rounded off to 8, use:
echo "Average: " . floor($avg);
If the average comes out to 8.33333 and would like it to be as 9 you would use:
echo "Average: " . ceil($avg);
ceil() function
floor() function
You may be mixing in stuff that can't be divided, like text, etc. I don't know what your text file looks like. intval may be having a problem with arrays. You may try:
foreach ($textfill as $vote) {
if(is_int($vote) {
$sum += $vote;
}
}
echo "Average: " . $sum;
Lower school math says:
foreach ($textfill as $vote) {
$sum += intval($vote);
}
$avg = $sum / count($textfill);
The average value is calculated by divide the sum with the number of votes. This line will print the average value:
echo "Average: " . $sum/count($textfill);
I am trying to create a binary/hexadecimal converter to convert a denary(base 10) number/value into binary and hexadecimal.
It works fine so far for binary until the input from the form is greater than 11 digits and over(string length), ruffly as it seems to variety. after 11 digits it starts adding " - " into the outcome. Im not sure were this is coming from as I don't have an " - " in the code.
I wasn't sure if this was something to do with large integers as I saw some other questions on that topic(not in php however it was java, so not sure if there is something simpler in php)
That said I was under the impression that form inputs were always strings.
To test if a variable is a number or a numeric string (such as form input, which is always a string), you must use is_numeric(). - from : http://www.php.net/manual/en/function.is-float.php
(haven't yet got to hexadecimal but needed to mention it as some of the following code contains parts for it.)
here is the php code (note: I do check user input just not added it yet)
$inpu = $_POST['number'];
$numinput = $_POST['number'];
if (is_numeric($numinput))
{
while ($numinput >= 1)
{
$binary .= $numinput % 2;
$numinput = $numinput / 2;
}
$mult = strlen($binary) % 4;
echo gettype($numinput) . "<br />";
echo gettype($binary) . "<br />";
echo gettype($mult) . "<br />";
echo $mult . "<br />";
while ($mult < 4)
{
$binary.= "0";
$mult++;
}
$revbinary = strrev($binary);
echo $inpu . " in binary = " . $revbinary ;
echo "<br /> <br />";
echo chunk_split($revbinary, 4);
echo "<br />" . gettype($revbinary) . "<br />";
echo gettype($inpu) . "<br />";
}
else
{
if (is_numeric($numinput))
{
echo "$numinput is over the max value of 255";
}
else
{
echo "your entry is not a vaild number <br />";
echo $numinput;
}
}
Im not looking for completed version of this code as you would ruin my fun, I am just wondering why there is a "-" being entered after 11 digits or so. It also did't add the symbol before I added :
$mult = strlen($binary) % 4;
echo $mult . "<br />";
while ($mult < 4)
{
$binary.= "0";
$mult++;
}
This was to split the binary into 4s ( 0011 1101 0010 0110 ).
Edit: wondered if this would be useful:
echo gettype($numinput); result double
echo gettype($binary); result string
echo gettype($mult); result integer
gettype($revbinary); result string
echo gettype($inpu); result string
still trying to work this out myself.
Any advice is much appreciated Thanks
I would suggest simply using decbin() and dechex(). Those are functions included in php, which do exactly what you're trying to accomplish.
You might want to check if it is a number first (like you are already doing).
Then cast it to an integer (through intval()) and then apply decbin() and dechex()
http://php.net/manual/de/function.decbin.php
http://www.php.net/manual/de/function.dechex.php
http://php.net/manual/de/function.intval.php
<?php
$number1 = 1;
$number2 = 2;
echo $number1.' + ' . $number2. ' = '.$number1+$number2;
?>
See the above program. It is giving output as 3. Why not it is giving output as:
1 + 2 = 3
+ and . have the same precedence.
echo $number1.' + ' . $number2. ' = '.($number1+$number2);
The operations are applied in order. I.e:
echo $number1.' + ' . $number2. ' = '.$number1+$number2;
Becomes:
echo '1 + 2 = '.$number1+$number2;
Becomes:
echo '1 + 2 = 1'+$number2;
Since this is addition PHP will convert the string to an int which gives 1.
So the final expression is:
echo 1 + 2;//Prints 3
You can indicate which operations to perform together using brackets:
echo $number1.' + ' . $number2. ' = '.($number1+$number2);
your desired output :-
<?php
$number1 = 1;
$number2 = 2;
echo $number1.'+ ' . $number2.'='.($number1+$number2);
?>
I am doing a profile quiz. This is just an example of code. Ultimately I will do a loop for all possible combinations. Basically, if the student chooses answer 3 to question 1 (what is your height - small, medium, large, xl, xxl) I want their pgheight to be stored as 4, sgheight as 9, cheight as 4, etc... My final array will consist of 16 $pos and 16 $attr with 5 scores for each combination. Hope this makes sense. Thanks for any help.
e.g.
function height(){
$pos=array("pg","sg","c");
$attr=array("height","weight","strength");
$pgheight=array(1,2,3,4,5);
$sgheight=array(6,7,8,9,10);
$cheight=array(1,2,3,4,5);
$ans=3;
$i=0;
// THIS IS THE CODE THAT DOESN'T SEEM TO WORK.
// My logic is $pgheight=$pgheight[3];
$pos[$i].$attr[$i]=$pos[$i].$attr[$i]."[".$ans."]";
echo $pgheight;
}
you either want to eval the statement or use two dollar signs. you're reusing the variable pgheight so its a bit confusing. let me give you an example instead.
$fruit = array("apples", "oranges", "pears");
$drinks = array("beer", "cider", "wine");
$krislikes = "drinks";
$whichone = 0;
echo "Kris likes " . ${$krislikes}[$whichone] . "<br>";
// or
$answer = $$krislikes;
echo "Kris likes " . $answer[$whichone] . "<br>";
// or
eval('$the_answer=$' . $krislikes . '[' . $whichone . '];');
echo "Kris likes " . $the_answer . "<br>";
hope that helps.
I'm getting error like PHP
Warning: Division by zero error.
I'm still and want to calculate some problems. If you can tell me, how can calculate antilog / log inverse with examples, I'll be more satisfied.
<?
if(isset($_POST['submit']))
{
$P=$_POST['P']; // P=100000
$rate=$_POST['rate']; // rate = 10.5
$R=($rate/100);
$N=$_POST['N']; // N = 78
echo $P ."<br>" ;
echo $R ."<br>" ;
echo $N ."<br>" ;
$NEW=($R/12); // NEW = .00875
$aa = (1+($NEW)); // aa = 1.00875
$ab = bcpow('$aa', '$N',16); // ab = 1.9729529246182467
$ac = ($ab-1); // ac = 0.9729529246182467
$ad = bcdiv('$ab', '$ac', 3); // Div by Zero Error
$M = ($P*$NEW) *($ad);
echo "The Installment is : " . $M . "<br>";
}
?>
The line with the problem:
$ad = bcdiv('$ab', '$ac', 3); // Div by Zero Error
The problem here is because $ab and $ac are in quotes. They shouldn't be.
Having them in quotes means that PHP sees $ab as being a string consisting of the characters $, a and b, instead of the numeric value of the $ab variable.
Remove the quotes, and it should start working.
The same applies to the bcpow() line.
bcpow('$aa', '$N',16); are you sure these variables get parsed? They are treated as a string in single quotes, and since there is no number they might be just bogus. (typing $aa^$n on a calculator will fail).
You can use bcpow("'".$aa."'", "'".$N."'",16); or try using double quotes.
I didn't understood your code as well, but here is the code that calculate Antilog / log of a value
<?php
$log = 11;
$e = 2.718281828;
$dn = 1;
// Calculate Antilog of $log = 11
$ans = pow($e, $log);
$antilog = round($ans*10000)/10000;
echo "<br /> Antilog : ".$antilog;
// Calculate Log of $log = 11
$ans = log($log)/$dn;
$log = round($ans*10000)/10000;
echo "<br /> Log : ".$log;
// Calculate Antilog / Log of $log = 11
echo "<br /> Antilog / Log : ".($antilog / $log);
?>
Result:
Antilog : 59874.1416
Log : 2.3979
Antilog / Log : 24969.407231327
Hope this help you, if else please provide more details (comments) on your code.
To narrow down where your issue is coming from:
string bcdiv ( string $left_operand , string $right_operand [, int $scale ] )
bcdiv will return Division by zero only if the right operand is 0, so you can backtrace this by assuming $ac is your culprint. Try echoing $ac before the bcdiv function call to ensure it is not empty.
I'm willing to bet that this line $ac = ($ab-1); // ac = 0.9729529246182467
$ac is going negative.
You should also remove your single quotes, don't take the manual so literal. You can still pass in an int or double and the function will convert it for you. even if you cast the variable as a double.
//WITHOUT QUOTES
$ab = '1.9729529246182467';
$ac = ($ab-1);
echo bcdiv($ab, $ac, 3);
//output (2.027)
//WITH QUOTES
$ab = '1.9729529246182467';
$ac = ($ab-1);
echo bcdiv($ab, '$ac', 3);
//output Warning (2): bcdiv() [function.bcdiv]: Division by zero