将此 C 函数转换为 PHP
Translate this C function to PHP
我正在尝试将以下 C 代码转换为 PHP,该代码基本上只是尝试将任意整数值转换为字符池中的字符:
#include <cstdint>
#include <cstring>
#include <iostream>
uint8_t GetCharacter(uint32_t value) {
static const char* valid_characters = "0123456789ABCDEFGHIJKLMOPQRSTUVWabcdefghijklmnopqrstuvw";
static const size_t valid_characters_l = strlen(valid_characters);
uint8_t c = valid_characters[value % valid_characters_l];
return valid_characters[(value << c) % valid_characters_l];
}
int main() {
uint32_t array[] = {176, 52, 608, 855};
for (size_t i=0; i < 4; i++) {
uint8_t c = GetCharacter(array[i]);
std::cout << array[i] << ": " << (uint32_t) c << "n";
}
return 0;
}
这会产生
176: 109
52: 114
608: 85
855: 65
然而,我能够想出的PHP代码产生以下内容:
176: 109
52: 114
608: 85
855: 104 // << Here's the problem
我非常确定我完全翻译了它,但我找不到问题。
<?php
function getCharacter($index) {
$chars = "0123456789ABCDEFGHIJKLMOPQRSTUVWabcdefghijklmnopqrstuvw";
$c = ord(substr($chars, $index % strlen($chars)));
return ord(substr($chars, ($index << $c) % strlen($chars)));
}
function main() {
$array = array(176, 52, 608, 855);
foreach ($array as $value) {
echo "$value: " . getCharacter($value) . "n";
}
}
main();
有人可以指出我解决这个问题的正确方向吗?
问题是($index << c)
3,586,129,920
>20亿,并且不能用有符号的32位整数正确表示。由于您没有在 php 中显式定义$value
的数据类型,因此我认为算术最终取决于实现。
实际上,令人惊讶的是,事情根本有效 - 我认为,您将 32 位数字移动大于 32 的值将导致未定义的行为。您可能需要重新考虑基础数学,特别是考虑代码的下溢/溢出行为。
作为一个潜在的解决方案,您可能会注意到您有有限数量的可能输入和相应的输出 - 您实际上可以创建一个直接查找表。我相信我这样做是正确的(使用经过一些修改的代码的C++版本) - 它没有导致 1:1 映射让我有点惊讶。查找字符串变为:
$lookupString = "6RQtrpp07TU4AP1IDKmjl8QD7WjitmwUAcjT3AT9MuAu3PUKJtIb5vS"
您的 php 代码可以简化为
$value = ord(substr($lookupString, $input % 55));
其中55
是lookupString
的长度。
有趣的观察:许多字符出现不止一次;其他字符从不使用。这意味着这不是一个非常"好"的编码方案(如果这是它想要的)。
作为参考,这是我用来确定查找字符串的代码:
#include <cstring>
#include <iostream>
static const char* valid_characters = "0123456789ABCDEFGHIJKLMOPQRSTUVWabcdefghijklmnopqrstuvw";
uint8_t GetCharacter(uint32_t value) {
static const size_t valid_characters_l = strlen(valid_characters);
uint8_t c = valid_characters[value % valid_characters_l];
return valid_characters[(value << c) % valid_characters_l];
}
int main() {
uint32_t array[] = {176, 52, 608, 855};
for (size_t i=0; i < 55; i++) {
uint8_t c = GetCharacter(i + '0');
std::cout << char(c);
}
std::cout << "n";
return 0;
}
你几乎肯定会遇到"问题",因为你在32位PHP上运行,或者在Windows上运行PHP(无论操作系统位数如何,它都不支持64位整数)。问题是您在移位操作中溢出了整数:
64 位 PHP:
PHP_INT_MAX: 9223372036854775807
C: 66, index: 176, strlen: 55, shift: 704, substr: mnopqrstuvw :: 176: 109
C: 117, index: 52, strlen: 55, shift: 468374361246531584, substr: 9ABCDEFGHIJKLMOPQRSTUVWabcdefghijklmnopqrstuvw :: 52: 57
C: 51, index: 608, strlen: 55, shift: 1369094286720630784, substr: hijklmnopqrstuvw :: 608: 104
C: 86, index: 855, strlen: 55, shift: 3586129920, substr: ABCDEFGHIJKLMOPQRSTUVWabcdefghijklmnopqrstuvw :: 855: 65
32 位 PHP:
PHP_INT_MAX: 2147483647
C: 66, index: 176, strlen: 55, shift: 704, substr: mnopqrstuvw :: 176: 109
C: 117, index: 52, strlen: 55, shift: 109051904, substr: rstuvw :: 52: 114
C: 51, index: 608, strlen: 55, shift: 318767104, substr: UVWabcdefghijklmnopqrstuvw :: 608: 85
C: 86, index: 855, strlen: 55, shift: -708837376, substr: hijklmnopqrstuvw :: 855: 104
不幸的是,PHP 在 32 位系统上根本不支持长整数(目前)。解决此问题的唯一方法是通过GMP或BCMath等外部软件包。当PHP v7.0在今年晚些时候发布时,这个问题应该会得到解决。
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 如何在PHPCPP库中将C++map<string,map<string>>转换为php::value?
- 如何将 ZVAL 转换为 PHP 扩展的矢量
- 将此 C 函数转换为 PHP
- 从 C++、C#、Perl 或 Java 转换为 PHP
- 将php代码转换为C(sha1算法)
- 将 vector<std::string> 转换为本机 PHP 数组
- 在Php - cpp中将Php::Object转换回c++对象
- 如何使用CURL将这样的PHP代码转换为C/ c++
- 将C++代码转换为PHP
- 将c++函数转换为PHP