C++ converting PHP code adding numbers to string - php

I'm trying to convert PHP code to C++.
$this->Key + 1 + log2p (floor($TimePlot/$this->kY)*M_PI-2*20
In PHP Key is string in C++ key2 is char*, timeplot is time_t and val is int.
key2 + 1 + log2(floor((double)timeplot/this->val*M_PI-2*20))
and the error is:
error C2111: '+' : pointer addition requires integral operand
I don't know what to do to make it working. Thanks in advance.

If your $this->key is string, and you want to end up with a string in C++ also, then you need to do something like this:
char bf[1024];
sprintf (bf, "%f", 1.0 + log2(floor((double)timeplot/this->val*M_PI-2*20)) );
std::string k = key2;
k += bf;
assuming everything else in your expression resolve to numeric values that can participate in numeric calculations. I used a buffer length of 1024 bytes here, you can adjust it accordingly.

Related

Why, when I convert a string into binary, does it miss the first zeros?

I try to convert any string into binary. But if binary start with zeros, it doesn't display it. All my test give me the binary value from the first 1 until end. Here my code :
$value = unpack('H*', $MESSAGE);
$binary .= base_convert($value[1], 16, 2);
For example when I tried to convert the character "%" it display : 100101 instead of : 00100101
Did I forget something?
Thanks.
Yacine
It is easy to see that the question boils down to the following:
Why base_convert($value[1], 16, 2) does not zero-pad the result?
The reason is that base_convert interprets the first argument as a number (not a string of bytes, for example); it stops converting the bytes after the most significant bit is reached:
static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
char buf[(sizeof(zend_ulong) << 3) + 1];
char *ptr, *end;
zend_ulong value;
if (Z_TYPE_P(arg) != IS_LONG || base < 2 || base > 36) {
return ZSTR_EMPTY_ALLOC();
}
value = Z_LVAL_P(arg);
end = ptr = buf + sizeof(buf) - 1;
*ptr = '\0';
do {
*--ptr = digits[value % base];
value /= base;
} while (ptr > buf && value);
return zend_string_init(ptr, end - ptr, 0);
(i.e. when the value becomes zero.) The behavior is correct, since it is possible to add any number of zeroes up after the most significant bit without changing the result, e.g. 100101 is equal to 00100101.
The function does not have a parameter that affects the formatting of the result. So, in order to achieve the desired output, you need to use other function(s) such as sprintf.

PHP: Signed Binary Strings

I'm having a problem with converting binary strings to signed integers
If you call decbin('-40'), php will output 1111111111111111111111111111111111111111111111111111111111011000
But if you call bindec(decbin('-40')), it will output 1.84467440737E+19 (or something similar, which is obviously not -40) because it "sees the most significant bit as another order of magnitude rather than as the sign bit" - php manual
Is there a way to convert a binary 64 bit binary string (much like the one output by decbin) string into a signed integer?
From the documentation, you cannot use bindec
bindec() interprets all binary_string values as unsigned integers. This is because bindec() sees the most significant bit as another order of magnitude rather than as the sign bit.
base_convert appears to ignore signing altogether.
If you know that your incoming string will always be 64 bit binary and you are not on a 32 bit system, it's quite easy to write a custom function.
Check if the string is 64 characters long.
Check if the most significant bit is a 1.
Flip all bits
Add 1
Negate
Here's a quick one I knocked together.
function bindec2($bin)
{
if (strlen($bin) == 64 && $bin[0] == '1') {
for ($i = 0; $i < 64; $i++) {
$bin[$i] = $bin[$i] == '1' ? '0' : '1';
}
return (bindec($bin) + 1) * -1;
}
return bindec($bin);
}
Use pack and unpack to convert between int and binary string.
// 'i' means signed integer
var_dump(unpack('i', pack('i', '-40'))); // gives you -40

Porting code using sizeof() from C++ to PHP

I have some C++ code (segment seen below), I need to convert this to another language (namely PHP). The code, as seen, uses structs, which PHP doesn't do. I know I can "kind of" emulate structs through objects/arrays, however, this isn't the same. That is not my main problem though. I need a way to implement the sizeof() function found in C++ (since PHP's sizeof() function just counts the number of elements in an array/object).
typedef unsigned long Offset;
typedef unsigned long Size;
struct Location {
Offset offset;
Size size;
};
struct Header {
unsigned long magic;
unsigned long version;
struct Location elements;
struct Location ids;
struct Location strings;
struct Location integers;
struct Location decimals;
struct Location files;
};
int Build() {
Header theheader;
theheader.magic = *((unsigned long*)"P3TF");
theheader.version = 272;
theheader.elements.offset = sizeof(theheader);
theheader.elements.size = element_offset;
theheader.ids.offset = ((theheader.elements.offset + theheader.elements.size + 15) / 16) * 16;
theheader.ids.size = ids_offset;
theheader.strings.offset = ((theheader.ids.offset + theheader.ids.size + 15) / 16) * 16;
theheader.strings.size = string_offset;
theheader.integers.offset = ((theheader.strings.offset + theheader.strings.size + 15) / 16) * 16;
theheader.integers.size = 0;
theheader.decimals.offset = ((theheader.integers.offset + theheader.integers.size + 15) / 16) * 16;
theheader.decimals.size = 0;
theheader.files.offset = ((theheader.decimals.offset + theheader.decimals.size + 15) / 16) * 16;
theheader.files.size = file_offset;
theheader.padding[0] = 0;
theheader.padding[1] = 0;
fwrite(&theheader, 1, sizeof(theheader), file_handle);
}
Can anyone please point me in the right direction on how to do this?
Any help would be appreciated.
Obviously recreating sizeof from C will be a difficult feat, as C is statically-typed and, traditionally, sizeof is evaluated at run-time by the compiler. PHP is also pretty quiet about its memory usage.
One method of dynamically grabbing the size of an object is to use memory_get_usage (official PHP reference) before and after the allocation of the object in question. Of course, you'll run into some fun calculations when you compare the two memory usage values, as storing the values into variables will allocate memory also.
This is a pretty shaky method of recreating sizeof, but if it works it works.
You could simply sum all sizes of the objects in the array or object. However, that still only gets the length of strings, etc. If you want the actual size of the binary representation of the object, you'll have to do some additional math, such as converting all ints to 32 bits (or 64) and appending a null byte to all UTF-8 strings. If you're using charsets, do make sure that they are single-byte or at least measurable in bytes.
PHP does not have a function that checks the memory size of an object.

sprintf() to truncate and not round a float to x decimal places?

When calculating a golf handicap differential you are supposed to truncate the answer to 1 decimal place without rounding. No idea why but...
I know how to do this using TRUNCATE() in mySQL
SELECT TRUNCATE( 2.365, 1 );
// outputs 2.3
but I was wondering if sprintf() could do this? The only way I know to work with decimal places in a float is ...
echo sprintf("%.1f", 2.365);
// outputs 2.4
What language is this in? Assuming it's C or one of its derivatives, and assuming you always want exactly one decimal place, and assuming your values are always non-negative, you can do this:
float val = 12.3456;
val = floor(val*10.0)/10.0;
sprintf("%.1f", val);
Is there a better way? Probably. This is just what comes to mind.
I find it easier to use string operations: let sprintf round to an extra significant digit, trim, then convert back to a float
function truncate_float(float $float, int $significantDigits = 4): float
{
$format = sprintf('%%.%df', $significantDigits + 1);
return (float) substr(sprintf($format, $float), 0, -1);
}

Why is the number 16 converted to float(6.1026988574311E_320) by PHP using Zend_Amf

The Zend_Amf specification states that a Number type returned from flash will map to a float in PHP. Fine. But why does the number 16 get returned as 6.1026988574311E_320 ? PHP version is 5.2.9 running on OS X.
I have tried forcing a cast to integer in PHP (the above value gets rounded to 0) and also from Actionscript using int(16) - the latter comes through as NULL. How can ensure that Flash returns an integer via AMF and that PHP can deal with it?
You have a classic endian problem. Looks like either Zend or flash is doing the wrong thing with the endianness of this double. Here is the a program that prints the double (and its hex value). It then reverses the endianness and prints it again.
#include <stdio.h>
#include <stdint.h>
int main(void)
{
double d = 16;
uint32_t *i = (uint32_t *)(&d);
uint8_t *c = (uint8_t *)(&d);
size_t j;
printf("%08x %08x %lg\n", i[1], i[0], d);
for(j = 0; j < sizeof(double) / 2; j++)
{
uint8_t tmp;
tmp = c[j];
c[j] = c[sizeof(double) - j - 1];
c[sizeof(double) - j - 1] = tmp;
}
printf("%08x %08x %lg\n", i[1], i[0], d);
return 0;
}
On an Intel (little endian processor), you get this output
40300000 00000000 16
00000000 00003040 6.1027e-320
Are you perhaps running this on a PPC Mac (big endian)? Seems like one of your tools is not doing the right thing on your architecture. File a bug with the vendors.
As a hacky workaround, I suggest turning your number into a string and then converting it back to a double on the other end.
I don't know entirely what is going wrong in your situation, but I think I may be able to partially illuminate what is happening to your code. I ran the following quick hack to test a theory:
void hexdump_double(double dbl)
{
assert(8 == sizeof(dbl));
printf("double: %02X %02X %02X %02X %02X %02X %02X %02X (%lg)\n",
((char *)&(dbl))[0],
((char *)&(dbl))[1],
((char *)&(dbl))[2],
((char *)&(dbl))[3],
((char *)&(dbl))[4],
((char *)&(dbl))[5],
((char *)&(dbl))[6],
((char *)&(dbl))[7],
dbl);
}
int main()
{
hexdump_double(6.1026988574311E-320);
}
Which produces some exciting output:
double: 40 30 00 00 00 00 00 00 (6.1027e-320)
As you can see, that little floating-point number isn't any random pattern of bits. However, it also doesn't look to be related to "16."
Where Zend_Amf documentation states that ActionScript Number type is returned as a PHP float, what is meant is the class Number documented by Adobe: Adobe.com Flex documentation. It does not mean that any "number" will be passed as a double.
An int with value less than 2^29 will be returned transmitted in AMF as an integer type, and I assume Zend_Amf will return this as an integer.
How are you transmitting the AMF object from your ActionScript? Is it feasible to dump the bytes being sent?

Categories