Incorrect calculation using decimals in php - php

I have some arrays, holding the numbers for a multiplication quiz. Here are some examples:
if($level==8){
$first=array(13,14,16,17,18,19);
$second=array(9,10,11,12,13,14,15,16,17,18,19);}
if($level==9){
$first=array(23,19,46,87,98,39);
$second=array(19,10,111,112,139,178,145,166,167,185,192);}
if($level>9){
$first=array(2.3,1.9,4.6,8.7,9.8,3.9);
$second=array(1.9,10,11.1,11.2,13.9,17.8,14.5,16.6,16.7,18.5,19.2);}
These numbers are used to calculate some answers that are placed on a button and the user has to click on the correct answer.
// the correct answer
$b=rand(0,5);
$c=rand(0,10);
$f=$first[$b];
$s=$second[$c];
$d=$f*$s;
// wrong answer no. 1
$w1a=rand(0,5);
$w1b=rand(0,10);
$w1c=$first[$w1a];
$w1d=$second[$w1b];
$w1e=$w1c*$w1d;
if ($w1e==$d){
wronganswer1();
}
// wrong answer no. 2
$w2a=rand(0,5);
$w2b=rand(0,10);
$w2c=$first[$w2a];
$w2d=$second[$w2b];
$w2e=$w2c*$w2d;
if ($w2e==$d){
wronganswer2();
}
There is a check on the receiving page of the POSTing to see if the user has indeed got the correct answer:
$b=$_POST["b"];
$c=$_POST["c"];
$subby=$_POST["sub"];
$d=$c * $b;
$score=$_SESSION["score"];
?>
</head>
<body>
<?php
if ($subby==$d){
echo "<script>correct.play()</script>";}
else{
echo "<script>wrong.play()</script>";
}
?>
<?php
if ($subby==$d) {
echo "Well done!";
$_SESSION["score"]=$_SESSION["score"]+1;
echo "<h3>The button you pressed said: ".$subby;
echo "</h3><br><h2>";
echo $b."x".$c."=".$subby;
echo "</h2><br>";
echo "<h3>Your streak is worth ".$_SESSION["score"];
}
else {
echo "<h1>No!<br>";
$_SESSION["score"]=0;
echo $b."x".$c."=".$d;
echo "<br>";
echo "Your streak has been reset to 0!</h1>";
}
Now, when I have whole numbers: no problem. But the decimals are causing a problem. My code is telling the player that a correct calculation is wrong!
I've spent some time echoing out simple decimal multiplications and the output is correct (so no truncating of decimals or anything like that)...
Why the inaccuracy?

I'm guessing that you are comparing floating point numbers in the same way as integers.
It can't possibly work because of the nature of floating point numbers.
You can't check equality of floating point values, but you can ask if their absolute difference is within a tolerance that you specify. Here's pseudo code to show what I mean:
float x = 1.1;
float y = 1.2;
float tolerance = 1.0e-3;
if (abs(x-y) <= tolerance) { // abs() is an absolute value function
print "within tolerance"
} else {
print "not within tolerance"
}

In the end I managed to get the desired result by casting my 'comparator' to a string (see top line of code):
if ($subby==(string)$d) {
echo "Well done!";
$_SESSION["score"]=$_SESSION["score"]+1;
echo "<h3>The button you pressed said: ".$subby;
echo "</h3><br><h2>";
echo $b."x".$c."=".$subby;
echo "</h2><br>";
echo "<h3>Your streak is worth ".$_SESSION["score"];
Thanks for the help of all who led me to the conclusion/knowledge that 'you can't compare floating values'.

Related

echo isset with condition

When people search for a real estate agent by zip code they will see a message on the site I'm working on that reads: There are x number of our Agents in your neighborhood.
x is the number determined by this php code:
<?php echo isset($total_record) ? $total_record : "";?>
if the number is Zero, the message sounds dumb (There are 0 number of...)
How do I change the message just for those cases with 0 as a search result? so that a different message appears? Something like - Sorry, we don't have any Agent in your immediate area.
Any help, much much appreciated.
Use a simple if statement:
if (isset($total_record) && $total_record > 0){
echo $total_record." number of our Agents in your neighborhood";
} else {
echo "Sorry, we don't have any Agent in your immediate area.";
}
if (isset($total_record))
{
if ($total_record > 0)
{
echo "There are {$total_record} of our Agents in your neighborhood.";
}
else
{
echo "There are no Agents in your neighborhood.";
}
}
Use the empty function rather than isset. The empty function checks if a variable exists and has a value. 0, false, and a few other values are also considered empty, check the manual for a full listing.
echo !empty($total_record) ? 'There are ' . $total_record . ' number of our Agents in your neighborhood.' : 'Sorry, we don\'t have any Agent in your immediate area.';

How to validate a input to numbers only

I'm making a form to allow numbers only. I'm trying to figure out the logic for the input to restrict numbers starting with 1,2,3,4,5.
This is my php code
<?php
$boton=#$_POST['btnParticipar'];
if (isset($boton)) {
$nombre=#$_POST['txtNumero'];
$simbolos=array('<','>','#','?','php','*','[a-zA-Z]');
foreach ($simbolos as $sim) {
$nombre=str_replace($sim,' ',$nombre);
}
echo $nombre;
}
?>
You could do it this way aswell. I do not know if it's a good solution, but it should work. The first section in the if-statement checks if the input is an integer, and the second section checks if the first number is 6, 7 or 8.
<?php
if(filter_var($_POST['txtNumero'], FILTER_VALIDATE_INT) AND in_array(substr($_POST['txtNumero'], 0, 1), array(6, 7, 8))) {
echo "Correct";
} else {
echo "Incorrect";
}
?>
I would suggest this regex:
if(isset($_POST['value']) AND preg_match('/^[6-8]/', $_POST['value'])){
// do whatever you want
}
As i only know from you that the input needs to start with 6,7,8, this may be the best solution.

PHP Auto-highlight cell depending on data from database

I am working on a PHP application and stumbled upon a problem on auto-highlighting.. I want to ask how to auto-highlight a cell of a table, whose data came from a database, after checking if the value is negative, 0, or positive, Red for negative, yellow for 0 and green for positive.
Please note that I have no experience regarding JavaScript or Ajax and rudimentary knowledge only on CSS. Thank you.
If needed, I can post any part of my code here.
It might be helpful for you:
function getSampleStatus($sampleid){
if($sampleid==1){
$color="#007334";
}elseif($sampleid==2){
$color="#3f96e8";
}elseif($sampleid==3){
$color="#ff9900";
}elseif($sampleid==4){
$color="#ff9770";
}
else{
$color="#ff0000";
}
$query='Select status from config where status_id='.$sampleid;
$this->_db->setQuery( $query );
$status =$this->_db->loadResult();
return "<span style='color:".$color.";padding-left:200px;'>".$status."</span>";
}
This function simply adds different colors depending on sample status.
For example:
For disapproved records, color red.
For Approved records, color green.
For Lab completed records, color yellow and so on..
Edit:
For Simplicity, try this:
$yourdatafromdatabase = 3; //which is either -ve, zero or positive
if($yourdatafromdatabase < 0){
$color="#FF0000"; //red for less than zero
}elseif($yourdatafromdatabase== 0){
$color="#FFFF00"; //yellow for zero
}
else{
$color="#00FF00"; //green for positive
}
echo "<span style=\"color: $color\"> <h1> Wow Color! </h1></span>";
?>
Working Demo:>>
just write css in table tag e.g
if ($value <0)
{echo "<td bgcolor=\"#FF0000\">$value</td>";}

PHP can't iterate through too high or too low

[Disclaimer: I am new to PHP, and I am just learning, so please no flamers, it really hinders the learning process when one is trying to learn, thank you.]
The code below runs, the only problem is that it does not tell the user when the number is too high or too low, I am doing something wrong, but I can't see the error?
<?php
//Starts our php document
if (!$number)
//if we have already defined number and started the game, this does not run
{
Echo"Please Choose a Number 1-100 <p>";
//gives the user instructions
$number = rand (1,100) ;
//creates number
}
else {
//this runs if the game is already in progress
if ($Num >$number)
{
Echo "Your number, $Num, is too high. Please try again<p>";
}
//if the number they guessed is bigger than number, lets user know, guess was high
elseif ($Num == $number)
{
Echo "Congratulations you have won!<p>";
//if the number they guessed was correct it lets them know they won
Echo "To play again, please Choose a Number 1-100 <p>";
$number = rand (1,100) ;
//it then starts the game again by choosing a new value for $number that they can guess
}
else
{
Echo "Your number, $Num, is too low. Please try again<p>";
}
//if the answer is neither correct or to high, it tells them it is too low
}
?>
<form action = "<?php Echo $_SERVER[’PHP_SELF’]; ?>" method = "post"> <p>
<!--this sends the form back to the same page we are on-->
Your Guess:<input name="Num" />
<input type = "submit" name = "Guess"/> <p>
<!--Allows the user to input their guess-->
<input type = "hidden" name = "number" value=<?php Echo $number ?>>
<!--keeps passing along the number value to keep it consistent till it is guessed-->
</form>
</body>
</html>
I am assuming $Num is undefined and I am assuming you are assuming it will be defined be cause it is defined in the form.
Try this at the start of your script:
if(!empty($_POST)) {
$Num = (int) $_POST['Num'];
}
$number is not automatically set to the value the <input> field has. (It was in early versions of PHP). You now have to use $_POST['number'] and $_POST['Num'] for this.
register_globals in your php.ini is probably Off (and that's a good thing) and therefore you can only access those variables through $_POST['Num'] and $_POST['number'] (you can just assign $number=$_POST['number'] at the beggining of your script)
also, sending the secret $number through form is not nice, you might want to read about php sessions
Suggestions:
1) use echo, not Echo
2) do not forget to close the p tag

Comparing string - woes in PHP

I want to allow the user to enter a coupon number in order to get a discount. After the coupon number is entered and submitted, the page reloads withe a tick showing that they have entered a correct amount.
The way I'm trying to do this is displaying the tick if the coupon amount is not £0.00. But the string comparison doesn't seem to work, since it always thinks that it is not £0.00. The code is as follows. The function coupon_amount() returns the coupon amount. coupon_amount() returns "£0.00" (including the pound sign)
<?php $coup_amount = coupon_amount(); ?>
<?php $zero_amount = "£0.00"; ?>
<?php if(strcmp($coup_amount, $zero_amount)== 0) { ?>
<?php echo 'Enter coupon code if applicable:' ?>
<input type='text' class='couponinput' name='coupon_num' id='coupon_num' value='coupons_name' />
<input type='submit' class='update-button' value='submitcoupon' />
<?php } else { ?>
<?php echo 'Thanks.' ?><input type='text' disabled='disabled' class='couponinput' name='coupon_num' id='coupon_num' value='coupons_name' />
<div class='tick'></div>
<?php } ?>
Am I doing something wrong with the comparison?
I followed Oscar's suggestion below, and here is the output. Seems to be an encoding problem. And the pound sign is not appearing properly for the zero_amount.
coup_amount: (£0.00) zero_amount: (�0.00)
coup_len:10 zero_len:5
strcmp: -1
coup_ascii: 38 zero_ascii:163
You should really be storing/working with the discount values as numbers, this would make the comparison much easier.
Have you tried printing out all the values?
<?php $coup_amount = coupon_amount(); ?>
<?php $zero_amount = "£0.00"; ?>
//print'em out
<pre>
<?php
echo "coup_amount: ($coup_amount) zero_amount: ($zero_amount) \n";
echo "coup_len:".strlen($coup_amount)." zero_len:".strlen($zero_amount)."\n";
echo "strcmp: ".strcmp($coup_amount, $zero_amount)."\n";
echo "coup_ascii: ".ord($coup_amount[0])." zero_ascii:".ord($zero_amount[0]);
?>
</pre>
Amendment
So yes, now that we can see the output from this, it seems like the coup-string is an UTF16 (10 bytes long) and the other is something else (5 bytes long).
(Preaching follows.) When dealing with money you should really take extra care to make sure numbers are handled correctly. We've just seen that strings are subject to encoding, and like others have pointed out, floats are subject to fractional errors. Your best bet is probably to try and express it in 1/100s using an integer, and to express the currency in a separate variable. (Preaching over.)
But I'm guessing the coupon_amount-function is used everywhere and you can't change it. Then you might wanna look into converting the two strings so that the are in the same format. Take a look at iconv.
<?php if(strcmp($coup_amount, $zero_amount)== 0) { ?>
Seems very unreadable compared to:
<?php if(coupon_amount() == 0) { ?>
If coupon_amount() returned the actual value, not the formatted string representation.
Are you able to change the coupon_amount() function to get rid of the pound symbol? the php function money_format is good for adding whatever the users currency symbol is to a string for displaying on the page (or which ever symbol you set the locale to)
In the future you will find yourself having to remove the pound symbol first before you do any arithmetic on the return value from coupon_amount()
There are a lot of things that seem insignificant to user, but may break string comparison
coupon_amount() may insert some spaces somewhere in returned value
coupon_amount() may return variable number of zeros
coupon_amount() may use comma instead of dot (depending on locale)
coupon_amount() may encode pound sign using some HTML entity
Said that, it is much better to compare numeric values, and then format number as currency.
the strcmp call seems ok, my bet is on the coupon_amount function.
The absurd lengths I had to go to to get this working :) .. I changed the first if statment to:
if((ord($coup_amount[0])==38) && (ord($coup_amount[1])==35)
&& (ord($coup_amount[2])==49) && (ord($coup_amount[3])==54)
&& (ord($coup_amount[4])==51) && (ord($coup_amount[5])==59)
&& (ord($coup_amount[6])==48) && (ord($coup_amount[7])==46)
&& (ord($coup_amount[8])==48) && (ord($coup_amount[9])==48)
&& (ord($coup_amount[10])==0))
have you triend comparing it without a pound sign?..
like this
substr($coup_amount, 1) == "0.00";
i see you're having problem when retrieving the pound sign so i think it is best to try this.

Categories