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.
Related
I'm having an issue when parsing a string to a long. I want the variable "695690829980893234" to be parsed to a long without any loss. I've looked around for a bit but nothing really seemed to have helped.
When using (double) $var it shows as a 4.2904753172133E+17 (which is not the way I need it)
Does anyone have any ideas? Much appreciated!
In standard PHP, the type long does not exist.
So, if you want to have a long integer, you may use the standard int type, or use an extension, such as BC or GMP.
Specifically, the value 695690829980893234 is in the integer range of 64bit PHP, but out of the integer range of 32bit PHP.
To convert to int:
First, please make sure the number is in the int range. Then just convert
$res = intval("695690829980893234");
if($res<PHP_INT_MAX){
// OK! inside the positive limitation
}
To convert to GMP
A GMP object represents an arbitrary length integer:
$res = gmp_init("695690829980893234");
Then, use GMP functions to operate the number, such as:
$res = gmp_add($res, gmp_init("100"));
$res = gmp_sub($res, gmp_init("200"));
and finally, convert it back to int or string:
$int = gmp_intval($res);
$str = gmp_strval($res);
Hope this answer helps.
Be sure you're running 64-bit version of PHP.
echo PHP_INT_SIZE;
8
Then it will cast string to int easily
$a = "695690829980893234";
$b = (int)$a;
var_dump($a, $b);
string(18) "695690829980893234"
int(695690829980893234)
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've read all over about arithmetic regarding floating point numbers, but I'm just trying to accurately store the darn things.
I have a mysql field with the type of DECIMAL (40,20).
I am saving a value in php of 46457.67469999996. After updating the record with this value, the end result is 46457.67470000000000000000. Not sure why it's being rounded at all just being saved to the database.
The value is not being converted to a string or anything beforehand. The field value that is passed into PDO is the value I expected to be saved and it is returned as a float... Perhaps it's because I'm saving a PHP float to a mysql decimal type where the rounding is occurring?
What am I missing here?
EDIT: Added example code that has the issue
// Query placeholder variables. Hard-coded for the example test
$query_vars = array(
":vendor_id" => 33154,
":year" => 2018,
":coop_committed_dollar" => 46457.67469999996,
":coop_committed_dollar_update" => 46457.67469999996
);
$statement = " INSERT INTO vendor_data_yearly
(vendor_id, year, coop_committed_dollar) VALUES
(:vendor_id, :year, :coop_committed_dollar)
ON DUPLICATE KEY UPDATE
coop_committed_dollar = :coop_committed_dollar_update;";
$query = $connection->conn->prepare($statement);
$query->execute($query_vars);
When I run this, the resulting value of coop_committed_dollar is 46457.67470000000000000000. This code is legit all I am doing.
Possible solution
// Note that I am casting the string using the BC Math library.
// I dunno how to just initialize the number (lame documentation), so I'm adding 0 to it.
$number = "46457.674699999967";
$number = bcadd("46457.674699999967", 0, 20);
$query_vars = array(
":vendor_id" => 33154,
":year" => 2018,
":coop_committed_dollar" => $number,
":coop_committed_dollar_update" => $number
);
$statement = " INSERT INTO vendor_data_yearly
(vendor_id, year, coop_committed_dollar) VALUES
(:vendor_id, :year, :coop_committed_dollar)
ON DUPLICATE KEY UPDATE
coop_committed_dollar = :coop_committed_dollar_update;";
$query = $conn->prepare($statement);
$query->execute($query_vars);
This results in the number as expected in the DB.
ONLY SOLUTION I FOUND TO WORK CORRECTLY
The data I am working with is passed in via ajax. I had to take a few steps to get this to work correctly.
Use ini_set('precision', 20);
Manually set the data in question to be a string BEFORE sending it via ajax so PHP would not round it, extended with extra floating point madness, padd it, etc.
I found that PHP would just not let me reliably work with large numbers coming from a variable set outside the script's scope (ajax). Once PHP got it's hands on the number, it would do what it had to do in order to make it make sense as a float.
If anyone has a better solution for this particular scenario I'm all ears and eyes :)
The problem is that PHP's precision is not allowing you to store the exact number you think you are storing.
When you set ":coop_committed_dollar" => 46457.67469999996
PHP is actually storing it as a different value, depending on the precision.
The solution is to store the value in PHP as a string instead of a float.
Since your question is: "what am I missing", I will try to provide an answer.
Basically it comes down to storing floats internally using binary representation. Since 46457.67469999996 cannot be exactly in binary (it ends up with an infinite number, similar to 33% (.3333...) in base-10), the closest rounding is used based on PHP's precision (set in php ini).
I was given a great explanation in this question that I asked a while back.
In your particular case, it also seems that the value that you are sending via AJAX is being stored as a float when parsed by PHP on the server-side. You want it to be stored as a string instead. If you're using json_decode, add this option: JSON_BIGINT_AS_STRING.
Suppose we have a string $str = "a"; and number $num = 2;
$str = 'a';
$num = 2;
echo $str*$num;
Output:
0
When performing arithmetic operations on a string operand, PHP will try to convert the string to a number.
It does this by looking for digits at the beginning of the string and will try to convert them into a value. If there are no digits, the value will be zero.
(There's an edge case for strings containing e or E (scientific notation), but that's not relevant here.)
Good Question.
Same i did ask to my teacher when i was in collage,
The answer is.
String * int= infinity; //According to scientific calculator answer is infinity.
but we need to continue our so program it provide 0.
it is made by code by default answer.
Simply said the string will be converted to an integer with a value of 0. This will include most of the cases when only alphabetic values are used. If you try to add a integer value at the beginning of the string it would in theory become a integer of that value.
I would recommend to read Why PHP Strings Equal Zero or Comparison Operators
Maybe you are looking for str_repeat, instead doing looping for that, its a default value that php serve to you, or you need to cast A into integer . When you try to do calculation for data that is not in Integer/float data type. Usually PHP auto-typecast the variables. In some cases it wont. Then we have to type cast it manually