开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

12
返回列表 发新帖
楼主: 笑人心
收起左侧

[易语言] 求大佬翻译js这段代码。

[复制链接]
结帖率:63% (15/24)
 楼主| 发表于 2025-2-20 20:06:54 | 显示全部楼层   贵州省黔东南苗族侗族自治州
sucess 发表于 2025-2-20 20:01
.版本 2
.支持库 spec

老哥,没有取随机小数和到16进制这个命令
回复

使用道具 举报

结帖率:86% (12/14)

签到天数: 3 天

发表于 2025-2-20 20:49:54 | 显示全部楼层   重庆市重庆市
这个还真不好弄,易语言有大数类型,然后并没有提供那些位移什么的操作
回复

使用道具 举报

发表于 2025-2-20 20:57:09 | 显示全部楼层   山东省泰安市
笑人心 发表于 2025-2-20 20:06
老哥,没有取随机小数和到16进制这个命令

ai写的.我看这个js的核心是去自己实现bigint这个函数及他的移位运算才行,不然得到的位数不一样.
    var r = BigInt(Date.now());
    console.log(r);
    var o = BigInt(Math.ceil(0x7ffffffe * Math.random()));
    console.log(o);
     r <<= BigInt(64);
     console.log(r);
    (r += o);
    console.log(r);
    var x =r.toString(36);
    console.log(x);
1740055735853n
859944180n
32098362833270640708573565288448n
32098362833270640708574425232628n
2efzk0wea1botndps24tw
回复

使用道具 举报

结帖率:43% (3/7)

签到天数: 1 天

发表于 2025-2-21 01:00:38 | 显示全部楼层   江苏省徐州市
原JS函数id()的作用是生成一个唯一的ID。具体步骤是:获取当前时间戳的毫秒数,转换为大整数r;然后生成一个0到0x7ffffffe之间的随机整数,同样转为大整数o。接着,将r左移64位,再加上o,最后将结果转为36进制字符串。

首先,处理时间戳部分。在Python中,可以使用time模块的time()函数获取当前时间戳,但返回的是浮点数,所以需要用int()转换为整数,再转为Python的int类型(因为JS的BigInt对应Python的int)。

然后是随机数部分。JS中的Math.ceil(0x7ffffffe * Math.random())生成的是0到0x7FFFFFFE之间的整数(包括0,不包括0x7FFFFFFE+1?)。在Python中,random模块的random()函数生成的是[0.0, 1.0)的浮点数,所以用random() * 0x7ffffffe,再用math.ceil的话,可能会得到0到0x7ffffffe之间的整数。不过这里需要注意,Math.ceil在JS中处理的是向上取整,比如当Math.random()返回0时,结果为0,而当接近1时,会是0x7ffffffe。但可能需要用math.floor或者调整计算方式,因为原JS代码中的Math.ceil可能有问题?或者是不是应该是Math.floor?或者可能原JS代码的意图是生成一个0x7ffffffe范围内的整数?

比如,假设Math.random()返回的是[0,1)的浮点数,乘以0x7ffffffe得到的是[0, 0x7ffffffe)的数,然后用Math.ceil的话,得到的是0到0x7ffffffe-1之间的整数?或者是否可能得到0x7ffffffe?比如当随机数是接近1时,比如0.99999999,乘以0x7ffffffe得到接近0x7ffffffe的数,Math.ceil之后就是0x7ffffffe。所以原代码中的o的取值范围是0到0x7ffffffe(包含)吗?

这可能需要确认,但暂时先按原样处理。在Python中,可以用random模块的random()乘以0x7ffffffe,然后用math.ceil,得到整数。不过要注意Python的math.ceil返回的是float类型,需要转换为int。

然后,r左移64位。在JS中,BigInt的左移是r <<= BigInt(64),即r = r << 64n。Python中,左移操作符是<<,所以r = r << 64。因为Python的int可以处理大整数,所以没问题。

然后将r和o相加,最后转为36进制字符串。JS的toString(36)在Python中可以用numpy.base_repr或者自己实现转换函数。不过Python的int类型有一个方法可以转换为字符串,但标准库中没有直接转36进制的函数。不过可以自己编写一个转换函数,或者使用base36的库。不过这里可能需要手动处理。或者,可以使用Python内置的int和字符串处理,但需要处理大写字母的问题,因为JS的toString(36)可能使用小写字母,而Python的某些方法可能大写。例如,数字转36进制通常用0-9和a-z。

所以,我需要实现一个将大整数转换为36进制字符串的函数,使用小写字母a-z。

现在,逐步分析:

1. 获取当前时间戳的毫秒数。JS中的Date.now()返回的是毫秒数,而Python的time.time()返回的是秒数,但带有小数部分。所以需要乘以1000,取整数部分。比如:

r = int(time.time() * 1000)

然后转为Python的int,对应JS的BigInt。

然后生成随机数o:Math.ceil(0x7ffffffe * Math.random())

在Python中:

import math

import random

o = math.ceil(random.random() * 0x7ffffffe)

但需要检查是否正确。比如,当random.random()返回0的时候,结果是0。当返回接近1时,乘以0x7ffffffe可能得到接近0x7ffffffe的数,ceil后是0x7ffffffe。所以o的范围是0到0x7ffffffe(包含)之间的整数?

是的。所以这样处理是对的。

然后将r左移64位:

r = (r << 64) + o

然后转换为36进制字符串。例如,在JS中,假设r是BigInt,左移64位后,加上o,得到一个很大的数,然后用toString(36)。

在Python中,处理大整数没有问题,但需要将结果转换为小写的36进制字符串。Python的内置函数int没有直接的方法,所以需要自己实现或者找方法。

可以使用以下函数:

def int_to_base36(num):

chars = '0123456789abcdefghijklmnopqrstuvwxyz'

if num == 0:

return '0'

res = []

while num > 0:

num, rem = divmod(num, 36)

res.append(chars[rem])

return ''.join(reversed(res))

这样就能将num转换为36进制的小写字符串。

综合起来,Python代码的大致步骤:

import time

import math

import random

def id():

r = int(time.time() * 1000)

o = math.ceil(random.random() * 0x7ffffffe)

r = (r << 64) + o

return int_to_base36(r)

然后实现int_to_base36函数。

然后测试一下,比如调用id()并打印。

不过需要测试是否正确,特别是位移和加法部分是否正确。

比如,假设当前时间戳为1625097600000(2021-07-01),转换为毫秒数是1625097600000。左移64位等于乘以2^64,加上o的值。这可能生成一个非常大的整数。然后转换为36进制。

需要注意,在Python中,左移运算优先级高于加法,所以(r <<64) + o是正确的。

另外,原JS代码中的r <<= BigInt(64),相当于将r左移64位后再赋值给r,然后r += o。所以实际上等同于r = (r << 64n) + o。所以在Python中,是r = (r <<64) + o。

这样处理是正确的。

现在,关于随机数部分的问题:原JS中的Math.ceil(0x7ffffffe * Math.random()),在JS中Math.random()返回的是[0,1)的浮点数,所以0x7ffffffe * Math.random()的范围是[0, 0x7ffffffe),然后Math.ceil之后,得到的是整数范围是0到0x7ffffffe-1吗?例如,当最大值时,比如0x7ffffffe * 0.999999999,这个数可能接近0x7ffffffe,ceil之后就是0x7ffffffe-1?或者当Math.random()返回最大的可能值时,比如接近1的时候,比如0.9999999999999999,这时0x7ffffffe *这个值可能等于0x7ffffffe - epsilon,ceil后是0x7ffffffe-1?或者是否有可能达到0x7ffffffe?

比如,假设Math.random()返回的最大值是小于1的最大可能值,例如,0.9999999999999999。假设0x7ffffffe是2147483646(因为0x7FFFFFFF是2147483647,所以0x7ffffffe是少1,即2147483646)。

当乘以这个最大值,得到的结果可能是接近2147483646 * 0.9999999999999999,约等于2147483645.999999999,ceil之后得到2147483646。这时候o的值就会是2147483646?或者是否有可能超过?

比如,当0x7ffffffe * Math.random() 的值刚好是整数的时候,比如等于某个整数n,那么ceil之后还是n。但是如果刚好n是2147483646的时候,比如当Math.random()等于1.0的时候,才会出现,但Math.random()不会返回1.0。所以最大的可能o是2147483646 -1?或者,是否可能达到2147483646?

比如,假设原JS中的0x7ffffffe是0x7FFFFFFE的值,即0x7ffffffe等于2147483646。所以,当Math.random()返回一个接近1的值,比如0.999999999999,乘以2147483646得到大约是2147483645.999999,Math.ceil之后变成2147483646?这可能会导致o的值可以是2147483646?

但根据Math.ceil的定义,是的。例如,当x是整数时,Math.ceil(x)就是x。但如果x的小数部分为0的话,否则,就向上取整。例如,如果0x7ffffffe * Math.random()得到的是2147483645.0000001,那么ceil之后是2147483646?或者我的数学可能有问题?

不,原式是Math.ceil(0x7ffffffe * Math.random())。例如,当Math.random()返回的值足够大,使得乘积的小数部分大于0,那么ceil会进位。例如,比如当乘积是2147483645.1,那么ceil之后是2147483646。这显然不正确,因为原意可能是生成一个不大于0x7ffffffe的整数?

这可能是一个错误?或者原代码是否正确?

比如,假设原代码的目的是让o的范围是0到0x7ffffffe之间的整数(包含两端)。那么Math.ceil可能会产生0到0x7ffffffe的值。例如,当Math.random()返回0时,乘积是0,ceil是0。当Math.random()返回接近1时,乘积接近0x7ffffffe,ceil之后可能等于0x7ffffffe,导致o的最大值为0x7ffffffe。因此,o的取值范围是0到0x7ffffffe(包含)?

如果是这样的话,那么在Python中,math.ceil(random.random() * 0x7ffffffe)会得到同样的结果吗?

比如,当random.random()返回接近1的数,乘积接近0x7ffffffe,ceil之后会是0x7ffffffe?

是的。例如,在Python中:

>>> import math

>>> import random

>>> random.seed(42)

>>> 0x7ffffffe

2147483646

>>> math.ceil(0.9999999999999999 * 2147483646)

2147483646

是的,这样得到的是2147483646。所以o的取值范围是0到2147483646,包括这两个端点?

那这样的话,在Python中的代码是正确的。所以原JS代码中的o的取值范围是0到0x7ffffffe(包含),所以Python中的处理是对的。

现在,关于左移64位的问题。在JS中,r是BigInt类型,左移64位,然后加上o。例如,假设Date.now()返回的时间戳是1625097600000,转换为BigInt后,左移64位,相当于乘以2^64。然后加上o,得到一个非常大的数。这个数在Python中可以直接处理,因为Python的int支持大整数。

然后,将这个数转换为36进制的字符串。在JS中,toString(36)会生成小写字母的字符串,比如0-9和a-z。Python中需要确保转换后的字符串也是小写。

所以,编写一个int_to_base36函数,将整数转换为小写的36进制字符串。

例如,当num是0,返回'0'。否则,反复取余数除以36,得到各个位的字符,然后逆序组合。

所以,函数实现如下:

def int_to_base36(num):

if num < 0:

raise ValueError("Negative number not supported")

chars = '0123456789abcdefghijklmnopqrstuvwxyz'

result = []

while num > 0:

num, rem = divmod(num, 36)

result.append(chars[rem])

return ''.join(reversed(result)) if result else '0'

这样就能正确转换。

现在,将各部分组合起来:

import time

import math

import random

def int_to_base36(num):

chars = '0123456789abcdefghijklmnopqrstuvwxyz'

if num == 0:

return '0'

res = []

while num > 0:

num, rem = divmod(num, 36)

res.append(chars[rem])

return ''.join(reversed(res))

def id():

r = int(time.time() * 1000)  # JS的Date.now()是毫秒级

o = math.ceil(random.random() * 0x7ffffffe)

r = (r << 64) + o

return int_to_base36(r)

print(id())

测试一下这个代码是否正确。例如,当时间戳是某个固定值,随机数也是固定值时,能否得到预期的结果?

比如,假设时间戳是1625097600000(对应的毫秒数),o是123456789。

r = 1625097600000 << 64 = 1625097600000 * 2^64。这个数非常大。然后加上o,得到的结果转换成36进制。

但这样的测试可能难以手动计算,不过可以对比JS代码的输出和Python代码的输出是否在相同输入下一致。

例如,在JS中,假设当前时间戳是1625097600000,随机数生成的是o=123456789。

那么在JS中的计算:

r = BigInt(1625097600000) << BigInt(64) → 1625097600000 * 2^64

然后 r += o → r = 1625097600000*2^64 + 123456789

然后toString(36)的结果。

在Python中,同样的计算:

r = 1625097600000 <<64 → 1625097600000 * (2**64)

加上123456789,然后转换为base36。

不过,这样的测试可能较为困难,但可以确保转换函数的正确性。

另外,需要处理较大的数值,但Python的int没有问题。

综上,Python代码应该能够正确实现原JS代码的功能。

代码解释:
时间戳处理
time.time() * 1000 获取毫秒级时间戳,int() 确保其为整数。

随机数生成
random.random() * 0x7ffffffe 生成 [0, 0x7ffffffe) 的浮点数,math.ceil() 确保结果为 [0, 0x7ffffffe] 的整数。

位运算与合并
将时间戳左移64位(相当于乘以2^64),然后加上随机数o,合并成一个128位的超大整数。

进制转换
自定义 int_to_base36 函数将合并后的整数转换为小写字母的36进制字符串,与JavaScript的 toString(36) 行为一致。
回复

使用道具 举报

结帖率:43% (3/7)

签到天数: 1 天

发表于 2025-2-21 01:03:21 | 显示全部楼层   江苏省徐州市
建议做个DLL调用,易语言看起来似乎不太够用
回复

使用道具 举报

结帖率:43% (3/7)

签到天数: 1 天

发表于 2025-2-21 01:04:16 | 显示全部楼层   江苏省徐州市
#include <chrono>
#include <random>
#include <string>
#include <algorithm>

// 128位无符号整数类型(需编译器支持)
using uint128_t = unsigned __int128;

std::string int_to_base36(uint128_t num) {
    const char* chars = "0123456789abcdefghijklmnopqrstuvwxyz";
    std::string res;
    if (num == 0) return "0";
    while (num > 0) {
        uint128_t rem = num % 36;
        res.push_back(chars[static_cast<size_t>(rem)]);
        num /= 36;
    }
    std::reverse(res.begin(), res.end());
    return res;
}

std::string generate_id() {
    // 获取毫秒级时间戳
    auto now = std::chrono::system_clock::now();
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        now.time_since_epoch()
    );
    uint64_t timestamp = ms.count();

    // 生成 [0, 0x7ffffffe] 的随机数
    std::random_device rd;
    std::mt19937_64 gen(rd());
    std::uniform_int_distribution<uint64_t> dist(0, 0x7ffffffe);
    uint64_t rand_num = dist(gen);

    // 合并为128位整数
    uint128_t combined = static_cast<uint128_t>(timestamp) << 64;
    combined |= rand_num; // 等价于 combined += rand_num

    // 转换为36进制
    return int_to_base36(combined);
}

// 示例用法
#include <iostream>
int main() {
    std::cout << generate_id() << std::endl;
    return 0;
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表