I have a small issue with BIG numbers where BC Maths function bcdiv is always returning zero on non-zero results.
For example :
echo bcdiv(40075036, 86164.098903691, 40);
Versus the traditional method :
echo (40075036/86164.098903691);
I am not sure why the discrepency. Do BC Math functions only work on strings, and if so, how can i convert int values into strings before hand (inline notation preferred such as (int)$myvar; ) --- if that is the problem.
The solution to this problem was as follows:
bcmath operations only work with strings. You can not pass any other type of data as the parameters as it will not do any calculations unless the values are (string).
The set of functions will not automatically convert or cast the data into string, and NO ERROR WILL BE RETURNED if passing other data types.
To pass the data that is stored in an integer, float, etc, the following code will work for dynamic conversion of the variable data as needed:
bcdiv((string)40075036, (string)86164.098903691, (string)40);
OR
$num1 = 12345;
$num2 = 45678;
$digits = 40;
bcdiv((string)$num1, (string)$num2, (string)$digits);
If the numbers are fixed and known BEFORE you pass (aka, they aren't coming from a database, and aren't pre-calculated), then you should use the function as follows :
bcdiv('40075036', '86164.098903691', '40');
Use the "bcscale" function - Set default scale parameter for all bc math functions.
Ex.:
bcscale(40);
echo bcdiv(40075036, 86164.098903691);
It worked for me. (php 7.1)
bcscale manual
Related
I need to convert string like 0x2fe84e3113d7b to the float type. This string comes from infura.io API as balance of the account. I've tried to use https://github.com/mbezhanov/ethereum-converter, but it makes no sense in this case (it always returns 0.00000 in any way). How to convert this string to 0.000842796652117371 with php?
use Bezhanov\Ethereum\Converter;
...
$this->converter = new Converter();
$weiValue = '0x1e1e83d93bb6ebb88bbaf';
dump($this->converter->fromWei($weiValue)); // returns 0.00000000000000000000000000000000000
$hexValue = hexdec($weiValue); // returns 2.2757423599815E+24
dump($this->converter->fromWei($hexValue)); // returns the same
I guess it caused by too long value on $hexValue (I mean converter can't convert long integers as it). But how to get the ether value from this hex?
https://www.investopedia.com/terms/w/wei.asp
1 Ether = 1,000,000,000,000,000,000 Wei (10^18)
and since this is currency, storing it as a floating point would be asinine, so it's got to be a 64-bit integer there.
Deleted my overwrought answer for a simple:
var_dump(
$wei = hexdec("0x2fe84e3113d7b"),
$wei / pow(10, 18)
);
Output:
int(842796652117371)
float(0.000842796652117370993)
Which, coincidentally, also illustrates why you don't want to use floats for currency. Also, WFM.
Still doesn't explain why you have:
$hexValue = hexdec($weiValue); // returns 2.2757423599815E+24
Quoted in your example as that's several orders of magnitude wrong for the supposed input.
So I'm doing some CTF and one of the challenge is about php type juggling. The code looks something like this
if($_GET['var1'] == hash('md4', $_GET['var1']))
{
//print flag
}
So I was 80% sure that I need to pass in an integer so it'll be true but all I can manipulate is the url. I tried using python request to do it but still failed.
import requests
url = 'http://example.com'
params = dict(var1=0)
r = requests.get(url=url, params=params)
Is there any special case where php will treat the variable pass into GET array as int? Or there is other way to do so?
The answer to this CTF can be found here https://medium.com/#Asm0d3us/part-1-php-tricks-in-web-ctf-challenges-e1981475b3e4
The general idea is to find a value which starts with 0e and its hash also starts with 0e. The page gives an example of 0e001233333333333334557778889 which produces a hash of 0e434041524824285414215559233446
This notation is called scientific notation. To understand why this kind of type juggling works you need to understand what both numbers are. If we convert from scientific notation to decimal it becomes obvious.
0e001233333333333334557778889 = 0×101233333333333334557778889
0e434041524824285414215559233446 = 0×10434041524824285414215559233446
From primary school maths we know that anything multiplied by 0 is 0, which means both numbers are 0.
All input provided in the $_GET or $_POST superglobals is of type string.
Thanks to PHP's type juggling system both strings are treated as floating point numbers written in scientific notation and when cast to float they both equal 0.
So I am trying to cast a string value of ie: '0.0000143' to actual FLOAT or DECIMAL number value (so it must not be a string after conversion), but the actual number of 0.0000143 as it needs to be sent through some API call and the API requires it to be structured like that and not have an actual string value.
Can anyone help me achieve this (or is it actually even possible to do)?. Since I am out of ideas
To make things more clear, I have tried all the type casting possibilities there are in PHP (it is not working as I do not need something like 1.4E-5 returned to me, but the actual value like 0.0000143).
You can use Type casting in order to achieve that:
$string = '0.0000143';
$intValue = (int)$string;
$floatValue = (float)$string;
I'm trying to parse basically an ini file without using parse_ini_file for a few reasons. I have the file parsing perfectly into a multidimensional array and am able to search through it properly and everything. The problem that I am having, is that I want the file to be parsed based on the type. There are strings, floats and integers in the file and I need to store these as such rather than all as strings.
The users will need to be able to get the values stored, so basically they would do "Get Float from Header section with the Budget key" and this would return 4.5. However if they tried to get the string or integer from the same section it would fail. I have it able to get the keys, but since they are all stored as strings that is the only thing that works. I'm wondering what how to change the type of the value from string to integer or float.
Anyone have any ideas how to do this?
It would be very difficult to accurately predict what type of value you are looking at. Strings could contain numbers, decimal points appear in sentences, etc...
If you are dealing with a custom ini file that you are generating for your own use, you might be able to encode the type of value into the ini settings. A standard setting may look like this -
default_username=Zamereon
So you could append or prepend the data type to the setting -
(s)default_username=Zamereon // one character depicting the data type,
(i)default_reputation=1 // you could use strpos.
default_balance=0.5=f // use list($name,$value,$type) = explode('=',$setting)
References -
strpos()
list()
explode()
Another suggestion would be to leave them as strings in your parsed multidimensional array and only convert them when you actually need them. Within a function or line of code dealing with some inputted data from the ini file, you'll know exactly what data type you'll need, if it's a float just cast it to a float as you need it. There's not real need to cast every variable to it's correct form right away because their value will not change in it's textual representation; The conversion only truly needs to take place before performing some further manipulations.
You can use type casting
Type casting in PHP works much as it does in C: the name of the
desired type is written in parentheses before the variable which is to
be cast.
<?php
$foo = 10; // $foo is an integer
$bar = (boolean) $foo; // $bar is a boolean
?>
The casts allowed are:
(int), (integer) - cast to integer
(bool), (boolean) - cast to boolean
(float), (double), (real) - cast to float
(string) - cast to string
(array) - cast to array
(object) - cast to object
(unset) - cast to NULL (PHP 5)
What is the PHP command that does something similar to intval(), but for decimals?
Eg. I have string "33.66" and I want to convert it to decimal value before sending it to MSSQL.
How about floatval()?
$f = floatval("33.66");
You can shave a few nanoseconds off of type conversions by using casting instead of a function call. But this is in the realm of micro-optimization, so don't worry about it unless you do millions of these operations per second.
$f = (float) "33.66";
I also recommend learning how to use sscanf() because sometimes it's the most convenient solution.
list($f) = sscanf("33.66", "%f");
If you mean a float:
$var = floatval("33.66")
Or
$var = (float)"33.66";
If you need the exact precision of a decimal, there is no such type in PHP. There is the Arbitrary Precision Mathematics extension, but it will return strings, so it's only usefull for you when performing calculations.
You could try floatval, but floats are potentially lossy.
You could try running the number through sprintf to get it to a more correct format. The format string %.2f would produce a floating-point-formatted number with two decimal places. Excess places get rounded.
I'm not sure if sprintf will convert the value to a float internally for formatting, so the lossy problem might still exist. That being said, if you're only worrying about two decimal places, you shouldn't need to worry about precision loss.
php is a loosely typed language. It doesn't matter if you have
$x = 33.66;
or
$x = "33.66";
sending it to mssql will be the same regardless.
Are you just wanting to make sure it is formatted properly, or is an actual float?