首页
统计
留言
友链
更多
图片
关于
Search
1
设置 Git 全局代理
49 阅读
2
软件开发 | flutter使用camera插件在安卓11以上的机器上调用availableCameras无法正常获得usb相机列表
48 阅读
3
scoop包管理器
47 阅读
4
Word图片压缩
45 阅读
5
利用深度搜索求解回溯问题的通用模板
45 阅读
默认分类
测试
技术开发
杂项
技术分享
相关配置
后端开发
异常处理
软件开发
登录
Search
标签搜索
java
golang
scoop
mysql
flutter
git
vue
hexo
sublime text
cpp
windows
redis
mc
mod
fabric
word
计算机网络
go
html
camera
Wisansiiz
累计撰写
32
篇文章
累计收到
2
条评论
首页
栏目
默认分类
测试
技术开发
杂项
技术分享
相关配置
后端开发
异常处理
软件开发
页面
统计
留言
友链
图片
关于
搜索到
32
篇与
的结果
2026-08-23
Scoop 数据库安装、Windows 服务与认证配置指南
Scoop 数据库安装、Windows 服务与认证配置指南本文记录在 Windows 上通过 Scoop 安装 MySQL LTS、PostgreSQL 和 Redis,并将它们配置为本机自动启动服务、启用密码认证和持久化数据的完整操作。适用场景:个人开发机、本地测试环境。Redis Windows 构建不建议作为生产部署方案;生产环境优先使用 Linux、容器或托管数据库。1. 当前部署状态数据库版本Windows 服务地址认证状态MySQL LTS9.7.2MySQL127.0.0.1:3306root 密码认证PostgreSQL18.6PostgreSQL127.0.0.1:5432scram-sha-256Redis8.10.1Redis127.0.0.1:6379ACL 密码认证三个服务均设置为 Automatic,并且只面向本机监听。主要持久化目录:D:\Scoop\persist\mysql-lts ├── data └── my.ini D:\Scoop\persist\postgresql └── data D:\Scoop\persist\redis ├── dump.rdb ├── redis.conf ├── users.acl └── service-runtime-8.10.12. 安装与更新 Scoop 软件包普通 PowerShell:scoop install mysql-lts postgresql redis查看安装状态和可用更新:scoop list scoop info mysql-lts scoop info postgresql scoop info redis更新三个数据库程序:scoop update mysql-lts postgresql redis不要在可复用脚本中假定 Scoop 一定安装在 D:\Scoop,可动态查询路径:$mysqlRoot = scoop prefix mysql-lts $postgresRoot = scoop prefix postgresql $redisRoot = scoop prefix redis3. MySQL LTS3.1 配置持久化与本机监听配置文件:D:\Scoop\persist\mysql-lts\my.ini[mysqld] datadir=D:/Scoop/persist/mysql-lts/data bind-address=127.0.0.1 mysqlx-bind-address=127.0.0.1 port=3306 [client] user=rootScoop 的 mysql-lts manifest 会持久化 data 和 my.ini,更新程序时不应重新初始化已有数据目录。3.2 注册 Windows 服务在管理员 PowerShell 中执行:$mysqlRoot = scoop prefix mysql-lts $mysqlIni = 'D:\Scoop\persist\mysql-lts\my.ini' & "$mysqlRoot\bin\mysqld.exe" ` --install MySQL ` "--defaults-file=$mysqlIni" Set-Service MySQL -StartupType Automatic Start-Service MySQL Get-Service MySQL服务命令使用 current 路径时,Scoop 更新后会通过目录链接指向新版本。3.3 设置或验证 root 密码连接时使用交互式密码提示,避免密码出现在命令历史和进程参数中:mysql --protocol=TCP --host=127.0.0.1 --port=3306 --user=root -p全新初始化且 root 尚无密码时,可在登录后执行:ALTER USER 'root'@'localhost' IDENTIFIED BY '替换为强密码';如果无密码登录返回 ERROR 1045,说明数据目录中的 root 已经设置过密码。除非确认需要重置,否则不要使用 --skip-grant-tables 覆盖未知密码,以免现有应用断连。3.4 创建应用账户应用程序不要直接使用 root。进入 MySQL 后执行:CREATE DATABASE app_db CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; CREATE USER 'app_user'@'localhost' IDENTIFIED BY '替换为独立强密码'; GRANT ALL PRIVILEGES ON app_db.* TO 'app_user'@'localhost'; SHOW GRANTS FOR 'app_user'@'localhost';连接示例:mysql://app_user:<password>@127.0.0.1:3306/app_db4. PostgreSQL4.1 注册 Windows 服务在管理员 PowerShell 中执行:$postgresRoot = scoop prefix postgresql $postgresData = 'D:\Scoop\persist\postgresql\data' & "$postgresRoot\bin\pg_ctl.exe" register ` -N PostgreSQL ` -D $postgresData ` -S auto Start-Service PostgreSQL Get-Service PostgreSQL4.2 设置管理员密码Scoop 首次初始化通常允许本机 trust 登录。先连接:psql --host=127.0.0.1 --port=5432 --username=postgres --dbname=postgres在 psql 中通过交互式提示设置密码:\password postgres4.3 强制使用 SCRAM 密码认证编辑:D:\Scoop\persist\postgresql\data\pg_hba.conf把本机规则中的 trust 改成 scram-sha-256:local all all scram-sha-256 host all all 127.0.0.1/32 scram-sha-256 host all all ::1/128 scram-sha-256 local replication all scram-sha-256 host replication all 127.0.0.1/32 scram-sha-256 host replication all ::1/128 scram-sha-256重新加载配置:$postgresRoot = scoop prefix postgresql & "$postgresRoot\bin\pg_ctl.exe" reload ` -D 'D:\Scoop\persist\postgresql\data'验证密码登录:psql --host=127.0.0.1 --port=5432 --username=postgres --dbname=postgres4.4 创建应用账户进入 psql 后:CREATE ROLE app_user LOGIN; \password app_user CREATE DATABASE app_db OWNER app_user;连接示例:postgresql://app_user:<password>@127.0.0.1:5432/app_db5. Redis5.1 Scoop Windows 包的服务包装器问题当前 redis manifest 下载普通的 msys2.zip,其中没有 README 提到的 RedisService.exe。同一发布页另有 msys2-with-Service.zip 资产。本机采用以下组合:Redis 主程序由 Scoop 安装和更新。使用同版本官方发布资产中的 RedisService.exe 注册 Windows 服务。数据、配置、ACL 和服务运行时全部放在 D:\Scoop\persist\redis。项目与发布页:https://github.com/redis-windows/redis-windowshttps://github.com/redis-windows/redis-windows/releases/tag/8.10.1Redis 8.10.1 with-Service 资产:https://github.com/redis-windows/redis-windows/releases/download/8.10.1/Redis-8.10.1-Windows-x64-msys2-with-Service.zip SHA-256: 8D7710C858EB9EF24685D040272FA42F6B045906CBAB14DC635697A20303AF1B下载后必须核验:$zip = "$env:TEMP\Redis-8.10.1-Windows-x64-msys2-with-Service.zip" $expected = '8D7710C858EB9EF24685D040272FA42F6B045906CBAB14DC635697A20303AF1B' curl.exe -L ` 'https://github.com/redis-windows/redis-windows/releases/download/8.10.1/Redis-8.10.1-Windows-x64-msys2-with-Service.zip' ` -o $zip $actual = (Get-FileHash -LiteralPath $zip -Algorithm SHA256).Hash if ($actual -ne $expected) { throw "Redis archive hash mismatch: $actual" }5.2 建立持久化目录管理员 PowerShell:$redisRoot = scoop prefix redis $redisPersist = 'D:\Scoop\persist\redis' New-Item -ItemType Directory -Path $redisPersist -Force | Out-Null if (Test-Path "$redisRoot\dump.rdb") { Copy-Item "$redisRoot\dump.rdb" "$redisPersist\dump.rdb" -Force } Copy-Item "$redisRoot\redis.conf" "$redisPersist\redis.conf" -Force核心配置:D:\Scoop\persist\redis\redis.confbind 127.0.0.1 -::1 protected-mode yes port 6379 dir D:/Scoop/persist/redis dbfilename dump.rdb logfile "" aclfile D:/Scoop/persist/redis/users.acl5.3 创建默认 ACL 密码Redis ACL 文件可以保存密码的 SHA-256,而不是明文密码。管理员 PowerShell 示例:$secure = Read-Host 'Redis default password' -AsSecureString $pointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secure) try { $plain = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($pointer) $bytes = [Text.Encoding]::UTF8.GetBytes($plain) $hash = [Convert]::ToHexString( [Security.Cryptography.SHA256]::HashData($bytes) ).ToLowerInvariant() $aclLine = "user default on #$hash ~* &* +@all`n" [IO.File]::WriteAllText( 'D:\Scoop\persist\redis\users.acl', $aclLine, [Text.UTF8Encoding]::new($false) ) } finally { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($pointer) Remove-Variable plain -ErrorAction SilentlyContinue }5.4 注册 Redis 服务将 with-Service 压缩包内容解压到类似目录:D:\Scoop\persist\redis\service-runtime-8.10.1管理员 PowerShell:$wrapper = 'D:\Scoop\persist\redis\service-runtime-8.10.1\RedisService.exe' $config = 'D:\Scoop\persist\redis\redis.conf' & $wrapper install ` -c $config ` --service-name Redis ` --display-name 'Redis Database Server (Scoop)' ` --description 'Redis Database Server (Scoop, official RedisService wrapper)' ` --start-mode auto Start-Service Redis Get-Service Redis验证认证:redis-cli --host 127.0.0.1 --port 6379 --user default --askpass ping成功结果:PONG5.5 创建应用 ACL 用户先使用默认管理员账户连接:redis-cli --host 127.0.0.1 --port 6379 --user default --askpass在 Redis CLI 中创建应用用户并保存 ACL:ACL SETUSER app_user on >替换为独立强密码 ~app:* +@read +@write +ping ACL SAVE ACL LIST~app:* 限制用户只能访问 app: 前缀的键。根据应用需要继续缩小命令权限,不要在生产环境直接授予 +@all。连接示例:redis://app_user:<password>@127.0.0.1:6379/06. 服务管理与验证查看状态:Get-Service MySQL,PostgreSQL,Redis启动、停止和重启:Start-Service MySQL,PostgreSQL,Redis Stop-Service MySQL,PostgreSQL,Redis Restart-Service MySQL,PostgreSQL,Redis查看服务实际启动命令:sc.exe qc MySQL sc.exe qc PostgreSQL sc.exe qc Redis客户端连接测试:mysql --host=127.0.0.1 --port=3306 --user=root -p psql --host=127.0.0.1 --port=5432 --username=postgres --dbname=postgres redis-cli --host 127.0.0.1 --port 6379 --user default --askpass ping查看端口监听情况需要管理员权限:Get-NetTCPConnection -State Listen -LocalPort 3306,5432,63797. 凭据管理本机凭据文件:C:\Users\Wisansiiz\.config\database-services\credentials.txt建议:不要把真实密码写入本仓库、Git、README 或共享脚本。应用使用独立低权限账户,不直接使用 root、postgres 或 Redis default。开发框架优先通过系统环境变量、.env.local 或密码管理器读取连接信息。.env* 应加入 .gitignore,提交前使用 git diff --cached 再检查一次。如果凭据曾出现在聊天、终端历史或日志中,按已泄漏处理并轮换。8. 更新、备份和升级注意事项更新前备份MySQL:mysqldump --host=127.0.0.1 --user=root -p ` --all-databases --single-transaction ` --result-file=mysql-all.sqlPostgreSQL:pg_dumpall --host=127.0.0.1 --username=postgres ` --file=postgres-all.sqlRedis:redis-cli --host 127.0.0.1 --port 6379 --user default --askpass save Copy-Item 'D:\Scoop\persist\redis\dump.rdb' '.\redis-dump-backup.rdb'版本升级MySQL 和 PostgreSQL 的 Scoop manifest 已声明数据目录持久化,但更新前仍应备份。PostgreSQL 跨主版本升级不能仅把旧数据目录指向新程序;应使用 pg_upgrade 或逻辑备份与恢复。Redis Scoop manifest 没有声明 dump.rdb、配置和 ACL 的持久化,因此必须继续使用独立的 D:\Scoop\persist\redis。Redis 更新后,需要取得相同新版本的 with-Service 资产、验证哈希、更新 service-runtime-<version>,然后重新注册服务。9. 常见问题MySQL 返回 ERROR 1045这通常表示 root 已有密码,不代表服务启动失败。先使用现有密码连接,不要直接重置授权表。Redis 报配置路径不存在普通 redis-server.exe 基于 MSYS2/Cygwin,命令行中的 Windows 路径可能被错误拼接。直接运行时应使用:/cygdrive/d/Scoop/persist/redis/redis.conf注册服务时优先使用同版本 RedisService.exe,由包装器处理路径转换。Redis 报 Can't open the log file服务模式应使用绝对路径,或者设置:logfile ""让服务管理器接管标准输出日志。Redis 服务长期停在 StopPending这是 NSSM 包装 MSYS2 Redis 时可能出现的停止兼容问题。本机最终方案已改用 Redis Windows 发布项目自带的 RedisService.exe。PowerShell 输出 PSReadLine prediction 警告在输出被重定向或无虚拟终端的会话中,Set-PSReadLineOption -PredictionSource History 可能提示无法启用预测。这与数据库安装、服务注册和运行状态无关。10. 移除服务执行前先完成数据备份。以下操作只删除 Windows 服务定义,不应直接删除持久化数据目录。管理员 PowerShell:Stop-Service MySQL,PostgreSQL,Redis & "$(scoop prefix mysql-lts)\bin\mysqld.exe" --remove MySQL & "$(scoop prefix postgresql)\bin\pg_ctl.exe" unregister -N PostgreSQL & 'D:\Scoop\persist\redis\service-runtime-8.10.1\RedisService.exe' ` uninstall --service-name Redis确认服务定义已经移除后,再决定是否执行 Scoop 卸载:scoop uninstall mysql-lts postgresql redis不要在没有备份和确认路径的情况下递归删除 D:\Scoop\persist\mysql-lts、postgresql 或 redis。
2026年08月23日
3 阅读
0 评论
0 点赞
2026-07-23
Pi Coding Agent:极简而可扩展的终端编程助手
从安装、日常使用到 Skills、Extensions 与会话树,认识 Pi Coding Agent 的核心设计与使用方式。
2026年07月23日
3 阅读
0 评论
0 点赞
2026-07-05
Android Studio 镜像加速 Gradle 下载
解决 Android Studio 首次同步和 Gradle 依赖下载慢的问题
2026年07月05日
3 阅读
0 评论
0 点赞
2026-06-14
摘录 | AI Agent工具调用机制理解
背景AI Agent 和普通大模型聊天最大的区别,是它不只会生成文本,还能调用工具完成任务。普通聊天更像是:用户提问 -> 模型回答Agent 更像是:用户提出目标 -> 模型判断下一步 -> 调用工具 -> 读取结果 -> 再判断下一步 -> 最终回答所以 Agent 的核心不是“模型更聪明”,而是让模型进入一个可以观察、行动、反馈的循环。Agent Loop一个最基础的 Agent Loop 可以理解成四步:接收用户目标模型决定下一步动作如果需要工具,就执行工具把工具结果放回上下文,让模型继续判断简单写成伪代码:while task_not_done: action = model(messages, tools) if action.type == "final": return action.content if action.type == "tool_call": result = run_tool(action.name, action.arguments) messages.append(result)这就是很多 Agent 系统最底层的结构。复杂系统会在上面继续加计划、记忆、权限、任务队列、子 Agent,但基础循环大体都是这个思路。工具是什么工具本质上就是提前暴露给模型的一组函数。比如:{ "name": "read_file", "description": "读取指定路径的文件内容", "parameters": { "path": { "type": "string", "description": "文件路径" } } }模型看到这个描述后,并不是直接执行代码,而是生成一个结构化调用请求:{ "name": "read_file", "arguments": { "path": "README.md" } }真正执行工具的是 Agent 运行时,不是模型本身。这一点很重要:模型负责“决定要调用什么”,系统负责“判断能不能调用、怎么调用、调用后怎么处理结果”。工具描述很重要工具描述写得不好,模型就容易乱用工具。比如一个搜索工具,如果只写:search: 搜索内容模型并不知道它搜索哪里、什么时候该用、返回什么。更好的描述应该包含:工具用途参数含义适合什么时候使用不适合什么时候使用返回结果格式比如:search_notes: 根据关键词搜索用户本地笔记。适合在用户询问自己记录过的内容时使用。不适合搜索互联网信息。返回匹配笔记标题和摘要。工具越多,描述越要清楚。否则 Agent 会把工具当成万能入口,导致调用链变乱。参数生成工具调用的一个常见问题是:模型生成的参数不一定可靠。比如工具要求:{ "user_id": "number", "limit": "number" }模型可能生成:{ "user_id": "abc", "limit": "很多" }所以工具执行前要做参数校验。模型生成参数 -> schema 校验 -> 权限判断 -> 执行工具不要相信模型生成的参数一定正确。它只是根据上下文猜了一个结构,运行时必须验证。工具结果回传工具执行完以后,结果不能只给用户看,还要放回模型上下文里。比如工具返回:{ "success": true, "content": "找到 3 条相关笔记", "data": [ { "title": "Flutter 本地存储", "summary": "记录了 shared_preferences 和 Drift 的区别" } ] }模型拿到结果后,才能继续组织最终回答。如果工具失败,也要把失败原因明确返回:{ "success": false, "error": "文件不存在" }不要只返回“失败了”,否则模型无法判断下一步该重试、换参数,还是直接告诉用户。权限边界Agent 能调用工具以后,权限边界就很重要。可以把工具分成几类:类型例子风险只读工具搜索、读取文件、查询状态较低写入工具创建文件、修改数据库中等外部动作发邮件、下单、支付、发布内容高系统操作执行命令、删除文件、修改配置高高风险工具不能让模型直接执行。比较稳的做法是:工具执行前做权限判断高风险动作要求用户确认记录完整调用日志限制工具可访问的目录、账号和数据范围Agent 的能力越强,越需要边界。否则它不是自动化助手,而是不受控的自动执行器。可观测性Agent 出问题时,经常不是最终回答能看出来的,而是中间某一步工具调用错了。所以日志至少要记录:模型选择了哪个工具生成了什么参数参数校验是否通过工具执行结果是什么失败原因是什么最终回答是否使用了工具结果调试 Agent 时,最好能看到完整轨迹:user: 帮我总结昨天的笔记 tool_call: search_notes({"date":"yesterday"}) tool_result: 找到 5 条笔记 assistant: 总结内容...没有轨迹,就只能猜模型为什么这么回答。小结AI Agent 的工具调用机制可以简单理解成:模型决定调用 -> 系统校验参数 -> 运行时执行工具 -> 结果回到上下文 -> 模型继续推理这里面真正关键的不是“调用函数”本身,而是:工具描述是否清楚参数是否可靠权限边界是否明确工具结果是否能继续被模型使用中间过程是否可追踪把这些基础做好,Agent 才会从一个会聊天的模型,变成一个能稳定执行任务的系统。
2026年06月14日
1 阅读
0 评论
0 点赞
2026-06-14
开发 | Flutter本地数据持久化怎么选
背景Flutter 应用只要不是纯展示页面,基本都会遇到本地数据持久化的问题。比如:保存用户登录状态保存主题、语言、开关配置缓存接口返回的数据保存聊天记录、账单、笔记等业务数据离线时继续使用,联网后再同步这些场景看起来都叫“保存到本地”,但实际适合的方案不一样。如果一开始选错了,后面很容易出现数据结构难维护、查询困难、迁移麻烦的问题。常见方案Flutter 里常见的本地持久化方案大概有这几类:方案适合场景不适合场景shared_preferences少量配置、开关、token复杂业务数据文件存储日志、缓存、导入导出文件频繁查询和更新SQLite结构化数据、本地业务表简单配置项Drift类型安全的 SQLite 封装很小的 demoHive/Isar本地对象存储、轻量缓存强关系型查询我的习惯是先按照“数据复杂度”和“查询需求”来选。shared_preferencesshared_preferences 适合保存少量键值数据,比如主题、语言、是否首次启动。final prefs = await SharedPreferences.getInstance(); await prefs.setBool('is_dark_mode', true); await prefs.setString('token', 'xxx'); final isDarkMode = prefs.getBool('is_dark_mode') ?? false; final token = prefs.getString('token');它的优点是简单,缺点也很明显:不适合存复杂对象,更不适合存列表型业务数据。比较适合保存:theme_modelocaleaccess_tokenfirst_launchlast_login_user_id不建议保存:聊天消息账单明细商品列表复杂用户资料文件存储文件存储适合保存一些不需要复杂查询的内容,比如日志、图片缓存、导入导出的 JSON。final directory = await getApplicationDocumentsDirectory(); final file = File('${directory.path}/notes.json'); await file.writeAsString(jsonEncode([ {'title': 'Flutter', 'content': 'local storage'}, ])); final content = await file.readAsString(); final data = jsonDecode(content);这种方式直观,但问题是查询、更新、删除都要自己处理。数据少的时候没问题,数据一多就会变得很难维护。如果数据本身天然就是文件,比如用户导出的备份、图片、日志,那文件存储很合适。如果是业务表数据,还是应该考虑数据库。SQLiteSQLite 适合保存结构化业务数据。比如一个记账应用,账单记录就很适合放到 SQLite:CREATE TABLE ledger_entries ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, amount REAL NOT NULL, type TEXT NOT NULL, created_at INTEGER NOT NULL );它的优点是:支持条件查询支持排序、分页支持事务支持索引数据结构清晰缺点是直接写 SQL 会比较繁琐,字段改动后迁移也要自己处理。Drift如果项目里本地数据比较重要,我更倾向于用 Drift。它本质上还是 SQLite,但提供了更好的类型安全和 Dart 层封装。表定义大概是这样:class LedgerEntries extends Table { IntColumn get id => integer().autoIncrement()(); TextColumn get title => text()(); RealColumn get amount => real()(); TextColumn get type => text()(); DateTimeColumn get createdAt => dateTime()(); }查询可以写成:Future<List<LedgerEntry>> getEntries() { return (select(ledgerEntries) ..orderBy([ (table) => OrderingTerm.desc(table.createdAt), ])) .get(); }插入数据:Future<int> insertEntry(LedgerEntriesCompanion entry) { return into(ledgerEntries).insert(entry); }Drift 的好处是数据层更清楚,适合业务长期迭代。缺点是上手成本比 shared_preferences 高,也需要配置代码生成。怎么选可以简单按这个规则判断:需求推荐方案保存几个配置项shared_preferences保存 token、主题、语言shared_preferences保存日志或导出文件文件存储保存列表数据SQLite 或 Drift需要条件查询、分页、排序SQLite 或 Drift项目会长期维护Drift只是快速 demoshared_preferences 或简单文件还有一个比较实用的判断方法:如果你开始想给数据加 id、createdAt、updatedAt,并且需要按条件查询,那基本就该用数据库了。分层建议不要在页面里直接操作数据库。比较清晰的结构是:presentation 页面和状态 domain 实体和业务接口 data 本地数据库、接口实现页面只调用 repository:final entries = await ledgerRepository.getEntries();具体数据来自 SQLite、接口还是缓存,页面不用关心。这样后面从本地数据切到服务端同步,也不会大面积改 UI。小结Flutter 本地持久化不要只看“哪个库简单”,要先看数据类型。我的选择习惯是:少量配置用 shared_preferences文件内容用文件存储业务数据用 SQLite长期维护的业务数据用 Drift如果只是保存一个开关,用数据库会显得太重;如果已经是账单、聊天记录、笔记这类数据,还继续用 JSON 文件或键值存储,后面维护成本会越来越高。
2026年06月14日
1 阅读
0 评论
0 点赞
2026-05-09
算法基础之埃氏筛
埃氏筛:高效求解素数的经典算法在算法题中,我们经常会遇到这样的问题:给定一个正整数 n,求出 1 ~ n 中所有的素数。最直接的做法是:对每个数 x,判断它是否只能被 1 和自身整除。但如果对每个数都从 2 试除到 sqrt(x),整体复杂度会比较高。这时,经典的 埃氏筛 就派上用场了。什么是埃氏筛?埃氏筛,全称 埃拉托色尼筛法,是一种用于快速筛选素数的算法。它的核心思想很简单:如果一个数是素数,那么它的倍数一定不是素数。例如:2 是素数,那么 4, 6, 8, 10... 都不是素数3 是素数,那么 6, 9, 12, 15... 都不是素数5 是素数,那么 10, 15, 20, 25... 都不是素数通过不断标记素数的倍数,我们就能筛掉所有合数,剩下的就是素数。算法过程假设我们要求 1 ~ n 中的所有素数。创建一个布尔数组 is_prime,初始认为所有数都是素数。将 0 和 1 标记为非素数。从 2 开始遍历到 sqrt(n)。如果当前数 i 仍然是素数,就把 i 的所有倍数标记为非素数。最后数组中仍然为 True 的下标就是素数。为什么从 i * i 开始标记?很多实现中会这样写:for j in range(i * i, n + 1, i):而不是从 2 * i 开始。原因是:对于素数 i,小于 i * i 的倍数已经被更小的素数筛过了。例如,当 i = 5 时:10 = 2 * 5,已经被 2 筛过15 = 3 * 5,已经被 3 筛过20 = 4 * 5,已经被 2 筛过所以从 25 开始即可。Python 代码实现def sieve(n: int) -> list[int]: if n < 2: return [] is_prime = [True] * (n + 1) is_prime[0] = False is_prime[1] = False for i in range(2, int(n ** 0.5) + 1): if is_prime[i]: for j in range(i * i, n + 1, i): is_prime[j] = False return [i for i in range(2, n + 1) if is_prime[i]] if __name__ == "__main__": print(sieve(50))输出结果:[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]代码解析1. 初始化素数数组is_prime = [True] * (n + 1) is_prime[0] = False is_prime[1] = False这里用 is_prime[i] 表示数字 i 是否为素数。一开始先假设所有数都是素数,然后再把 0 和 1 标记为非素数。2. 遍历可能的因子for i in range(2, int(n ** 0.5) + 1):外层循环只需要遍历到 sqrt(n)。如果一个合数存在大于 sqrt(n) 的因子,那么它一定也存在一个小于等于 sqrt(n) 的因子。因此,只要筛到平方根即可。3. 标记倍数for j in range(i * i, n + 1, i): is_prime[j] = False如果 i 是素数,就将 i 的倍数全部标记为非素数。这里从 i * i 开始,是因为更小的倍数已经在之前被筛过了。4. 收集答案return [i for i in range(2, n + 1) if is_prime[i]]最后遍历 is_prime 数组,把仍然为 True 的数字收集起来,就是 1 ~ n 中所有的素数。复杂度分析埃氏筛的时间复杂度是:O(n log log n)空间复杂度是:O(n)相比逐个判断素数的做法,埃氏筛在需要求出大量素数时效率非常高。常见细节1. 0 和 1 不是素数素数定义是大于 1,并且只能被 1 和自身整除的整数。因此:is_prime[0] = False is_prime[1] = False是必要的。2. 外层循环只需要到 sqrt(n)写成:for i in range(2, int(n ** 0.5) + 1):即可。如果不想使用浮点数,也可以写成:i = 2 while i * i <= n: ... i += 13. n < 2 时直接返回空列表因为小于 2 的范围内不存在素数:if n < 2: return []总结埃氏筛是求素数问题中非常经典的算法。它不是一个一个判断每个数是不是素数,而是反过来利用素数去筛掉它的倍数。这个思想非常重要:通过批量排除合数,快速得到所有素数。适合使用埃氏筛的场景包括:求 1 ~ n 中所有素数统计素数个数预处理素数表多次查询某个数是否为素数如果题目中出现“大范围内求素数”或“多次判断素数”,埃氏筛通常就是首选方案。
2026年05月09日
1 阅读
0 评论
0 点赞
2026-03-28
入坑mac-1
macOS 包管理器 Homebrew 完全配置指南前言Homebrew 是 macOS 上最受欢迎的包管理工具,被誉为"macOS 缺失的包管理器"。本文将详细介绍 Homebrew 的安装、配置以及常用命令,帮你快速搭建开发环境。一、Homebrew 是什么Homebrew 可以让你轻松安装和管理 macOS 原生没有预装的工具和软件,比如命令行工具(git、node、python 等)、macOS 应用(通过 Homebrew Cask)以及开发库和依赖。二、安装 Homebrew方法一:官方安装(需要梯子)/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"方法二:国内镜像安装(推荐)如果你在大陆地区,官方安装可能很慢,可以使用国内镜像:/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"这个脚本由国内开发者维护,会自动配置清华/中科大等镜像源,下载速度会快很多。验证安装brew doctor三、配置 PATH 环境变量安装完成后,需要将 Homebrew 的路径添加到配置文件:# 编辑配置文件(以 zsh 为例) nano ~/.zshrc # Apple Silicon Mac 添加 eval "$(/opt/homebrew/bin/brew shellenv)" # Intel Mac 添加 # eval "$(/usr/local/bin/brew shellenv)" # 使配置生效 source ~/.zshrc四、常用命令安装与管理包# 安装包 brew install git brew install nodejs # 卸载包 brew uninstall git # 查看已安装的包 brew list # 搜索包 brew search gitHomebrew Cask(安装 GUI 应用)# 安装 GUI 应用 brew install --cask visual-studio-code brew install --cask google-chrome # 卸载 GUI 应用 brew uninstall --cask visual-studio-code五、实用技巧批处理安装常用工具# 一次性安装多个包 brew install git node python go # 一次性安装多个 GUI 应用 brew install --cask visual-studio-code google-chrome其他常用命令# 更新 Homebrew 自身 brew update # 升级所有包 brew upgrade # 查看过时包 brew outdated # 清理旧版本 brew cleanup六、常见问题Q: Intel 和 Apple Silicon Mac 有什么区别?Mac 类型Homebrew 安装路径Intel Mac/usr/local/Apple Silicon/opt/homebrew/Q: Homebrew 命令找不到?source ~/.zshrc七、推荐安装的开发工具# 版本管理 brew install git gh # Node.js 生态 brew install node npm # Python brew install python pyenv # 容器 brew install --cask docker # 编辑器 brew install --cask visual-studio-code jetbrains-toolbox
2026年03月28日
2 阅读
0 评论
0 点赞
2026-03-10
开发 | flutter页面布局问题
开发 | flutter页面布局问题遇到的问题在flutter中使用 SafeArea 进行页面布局并且让页面进行全屏展示时会出现当下拉菜单栏时顶部任务栏会出现并挤压页面,导致页面高度变矮,影响页面显示。SafeArea 内部依赖 MediaQuery.of(context).padding 来添加内边距下拉通知栏时,系统状态栏和底部虚拟导航栏短暂出现,MediaQuery.padding 值发生变化SafeArea 响应这个变化,动态调整 padding,导致页面内容区域忽大忽小Scaffold( resizeToAvoidBottomInset: false, body: SafeArea(child: _buildLandscapeView()), // SafeArea );解决方案用 MediaQuery.removePadding 将 top/bottom/left/right 的 padding 全部移除这样即使系统 UI 短暂出现,页面也不会因为 padding 变化而重新布局配合 immersiveSticky 模式和 SystemUIChangeCallback 回调,系统栏会以半透明覆盖层形式短暂显示,不影响页面尺寸Scaffold( resizeToAvoidBottomInset: false, body: MediaQuery.removePadding( context: context, removeTop: true, removeBottom: true, removeLeft: true, removeRight: true, child: _buildLandscapeView(), ), );
2026年03月10日
40 阅读
0 评论
0 点赞
2026-02-20
goFrame配置文件的参数
goFrame配置文件的参数项目config# https://goframe.org/docs/web/server-config-file-template server: address: ":8000" openapiPath: "/api.json" swaggerPath: "/swagger" # https://goframe.org/docs/core/glog-config logger: level: "all" stdout: true path: "resource/log" rotate: "daily" rotateBackupLimit: 7 rotateBackupExpire: "7d" rotateBackupCompress: 9 # https://goframe.org/docs/core/gdb-config-file database: logger: - path: "resource/log/sql" level: "all" stdout: true default: link: "pgsql:postgres:postgres@tcp(127.0.0.1:5432)/go_admin" debug: true gToken: # 缓存模式 1 gcache 2 gredis 3 gfile cacheMode: 2 # 是否支持多端登录 multiLogin: true redis: default: address: 127.0.0.1:6379 db: 0 pass: 123456 cache: address: 127.0.0.1:6379 db: 1 pass: 123456 idleTimeout: 600rbac config[request_definition] r = sub, obj, act [policy_definition] p = sub, obj, act [role_definition] g = _, _ [policy_effect] e = some(where (p.eft == allow)) [matchers] m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)
2026年02月20日
43 阅读
0 评论
0 点赞
1
2
...
4