C++数位分离:从取模除法到健壮实现的完整指南
1. 从一道看似简单的面试题说起“给定一个三位整数输出它的个位、十位、百位数字。” 这大概是每个C初学者甚至很多面试者在技术一面时都可能遇到的题目。乍一看这太简单了不就是用取模和除法吗我见过太多简历上写着“精通C”的候选人在面对这道题时要么是写了个只能处理三位数的“硬编码”版本要么是代码里充斥着魔法数字要么是完全没考虑边界和异常情况。这道题就像一面镜子能清晰地照出一个程序员对C基础、问题抽象能力以及代码健壮性思考的深浅。今天我们就以这道题为引子深入聊聊在C中如何优雅、健壮地处理“数位分离”这个基础但重要的问题并延伸到更通用的场景。2. 核心原理为什么取模和除法是数位分离的基石要理解如何分离数位首先得回到我们最熟悉的十进制数系统。当我们写下数字123时它实际上表示的是1 * 10^2 2 * 10^1 3 * 10^0。这里的10就是基数。计算机存储整数时并不关心它是十进制、二进制还是十六进制它只存储这个数值本身。当我们想要获取特定数位上的数字时本质上是在做“按权分解”的逆过程。取模运算%在这里扮演了“获取余数”的角色。对一个整数n进行n % 10操作得到的就是n除以10的余数。由于我们使用十进制这个余数恰好就是n的个位数字。因为无论n多大n % 10的结果范围永远是0~9这正是个位数字的所有可能。整数除法运算/在C中当两个整数相除时结果会被截断小数部分只保留整数商。n / 10操作的效果是“去掉n的个位数”。例如123 / 10 12。你可以理解为将数字整体向右移动了一位十进制下原来的十位变成了新的个位。将这两个运算结合就构成了数位分离的基本算法先取模得到当前最低位个位再除以10“削掉”这个已经处理的最低位为获取下一位做准备。这个过程可以循环进行直到被处理的数变成0。这里有一个关键点循环终止的条件是n ! 0而不是n 0。如果你用n 0那么对于负数如-123循环根本不会进入这通常不是我们想要的结果。在数位分离的语境下我们通常关心的是数字的绝对值形式下的各个数位或者需要特别处理负号。因此更健壮的做法是先处理符号再对绝对值进行数位分离操作。3. 基础实现从“玩具代码”到“工业级”雏形我们先从一个最直接、但问题最多的实现开始然后一步步重构它。3.1 版本一初学者的“硬编码”版本#include iostream using namespace std; int main() { int num 123; int ge num % 10; int shi (num / 10) % 10; int bai num / 100; cout 百位: bai , 十位: shi , 个位: ge endl; return 0; }代码分析这段代码能正确输出123的各个数位。但它存在几个明显问题魔法数字代码中直接出现了10和100。这些数字缺乏语义如果将来要处理四位数就需要修改多处容易出错。功能僵化它只能处理恰好三位的正整数。输入12或1234输出就是错误的12的百位会被计算为01234的百位计算的是千位数字。未处理负数输入-123百位计算是-1这显然不符合我们对“百位数字”的认知。未处理零输入0个位输出正确为0但十位和百位的计算过程 (0/10和0/100) 虽然结果也是0但逻辑上依赖于特定的整数除法规则。这个版本仅适用于教学演示一个特定例子几乎没有实用价值。3.2 版本二引入循环的通用正数处理版本为了解决位数固定的问题我们需要一个通用的方法。思路是从低位到高位即从个位开始依次取出数字并存储起来。由于我们取出顺序是个、十、百……但通常我们想按百、十、个的顺序输出所以存储后需要反转或者我们可以换一种思路先确定数字的位数再从高位向低位取。这里先展示从低位到高位取并用容器存储的方法#include iostream #include vector using namespace std; void printDigits(int num) { if (num 0) { cout 数字为0个位是0 endl; return; } // 处理负数我们通常输出其绝对值的数位并标注负号 bool isNegative false; if (num 0) { isNegative true; num -num; // 取绝对值进行处理 } vectorint digits; int temp num; // 循环取出每一位 while (temp 0) { int digit temp % 10; // 取出当前个位 digits.push_back(digit); temp temp / 10; // 削掉当前个位 } // 输出结果注意digits中存储顺序是反的个位在前 if (isNegative) { cout -; } cout num 的各位数字从高位到低位是: ; // 反向遍历vector for (auto it digits.rbegin(); it ! digits.rend(); it) { cout *it ; } cout endl; } int main() { printDigits(12345); // 输出: 12345 的各位数字是: 1 2 3 4 5 printDigits(-678); // 输出: -678 的各位数字是: 6 7 8 printDigits(0); // 输出: 数字为0个位是0 return 0; }代码分析这个版本有了质的飞跃通用性可以处理任意位数的正整数和零。负数处理通过取绝对值输出了负数绝对值部分的数位并加上了负号标识。这是一种常见且合理的处理方式。结构清晰使用了函数封装逻辑分离。使用了标准库容器std::vector动态存储数位避免了固定数组大小的限制。注意这里循环条件是while (temp 0)。对于正数和零的特殊处理是合理的。如果我们希望一个函数同时处理正负数的“数位值”例如-123的个位是3那么应该在函数开始时统一取绝对值int temp abs(num)并记录原始符号。abs()函数在cstdlib或cmath中。3.3 版本三直接获取指定位上的数字有时我们不需要所有数位只想获取特定位置如百位的数字。我们需要一个更数学化的方法。对于一个整数num其第k位从个位为第0位开始计数的数字可以用公式表示digit_k (num / (10^k)) % 10例如对于12345个位(k0):(12345 / 1) % 10 12345 % 10 5十位(k1):(12345 / 10) % 10 1234 % 10 4百位(k2):(12345 / 100) % 10 123 % 10 3实现代码如下#include iostream #include cmath // 用于pow函数注意浮点精度问题 using namespace std; // 获取整数num的第k位数字个位为第0位 int getDigit(int num, int k) { // 处理负数取其绝对值 num abs(num); // 计算除数10的k次方 long long divisor 1; for (int i 0; i k; i) { divisor * 10; } // 注意使用pow(10, k)在k较大时可能有浮点精度误差自己累乘更安全 // 如果数字的位数小于k则返回0例如123的千位是0 if (num divisor) { return 0; } return (num / divisor) % 10; } int main() { int num 12345; cout num 的百位数字是: getDigit(num, 2) endl; // 输出 3 cout num 的千位数字是: getDigit(num, 3) endl; // 输出 2 cout num 的万位数字是: getDigit(num, 4) endl; // 输出 1 cout num 的十万位数字是: getDigit(num, 5) endl; // 输出 0 cout -678的十位数字是: getDigit(-678, 1) endl; // 输出 7 return 0; }代码分析这个getDigit函数非常实用和清晰。它明确了一个重要概念数位索引。个位是第0位十位是第1位以此类推。这符合计算机中常见的“从0开始”的索引习惯。函数内部先取绝对值保证了负数输入也能得到其数字部分的指定位。同时它处理了“越界”访问请求的位超出数字实际长度的情况返回0这在逻辑上是合理的就像数字前面有无限个0一样。重要提示计算10^k时我选择用循环累乘而不是std::pow(10, k)。这是因为pow是浮点数函数对于较大的k可能存在微小的精度误差导致转换为整数时出错例如pow(10, 2)理论上得到100.0但浮点误差可能得到99.999999转为int就成了99。在整数运算中自己用整数乘法累乘是绝对安全且高效的做法。4. 深入边界那些容易被忽略的“坑”写一个能跑的例子容易写一个在任何情况下都表现正确的程序难。下面我们来系统性地探讨数位分离中的边界情况和陷阱。4.1 整数溢出的幽灵这是最隐蔽也最危险的坑。回顾我们的通用循环while (temp 0) { digits.push_back(temp % 10); temp temp / 10; }以及直接取位的函数long long divisor 1; for (int i 0; i k; i) { divisor * 10; // 可能溢出 }问题在哪divisor的溢出如果k很大比如k20divisor在计算10^20时会远远超过long long所能表示的范围通常是9.22e18左右导致溢出结果是未定义的。输入num本身是INT_MIN在int num -2147483648(INT_MIN) 时我们常用的取绝对值操作num -num或num abs(num)会怎样在补码表示中-INT_MIN的值超出了int的正数表示范围会导致溢出这是一个经典陷阱。解决方案对于divisor溢出在函数中增加对k的合理性检查。对于一个32位int其最大值约21亿10位数所以k大于9或10时就可以直接返回0或报错。更安全的是使用long long类型并提前判断divisor是否在计算过程中超过LLONG_MAX / 10。对于INT_MIN这是处理负数时的一个特例。安全的做法是先将int转换为范围更大的类型如long long再做取绝对值运算。long long safeNum llabs(static_castlong long(num)); // 使用 llabs4.2 零和负零的迷思零需要特殊处理吗在我们的循环版本中while (temp 0)会导致输入0时循环一次都不执行digits向量为空。这不符合“0有一个个位数0”的直觉。因此我们必须在循环前对0进行特判就像版本二所做的那样。关于“负零”在标准的整数表示中不存在-0这个值。0的二进制表示是唯一的。所以不用担心这个问题。4.3 前导零的取舍有时我们会有“输出固定位数”的需求比如将数字7格式化为三位数输出 “007”。这本质上是数位分离和格式化输出的结合。我们的getDigit函数在位数不足时返回0正好可以用于这种场景。void printAsFixedWidth(int num, int width) { bool isNeg (num 0); long long safeNum llabs(static_castlong long(num)); // 预留符号位 if (isNeg) { cout -; width--; // 宽度包含符号位 } // 从最高位width-1位开始取 for (int k width - 1; k 0; --k) { long long divisor 1; for (int i 0; i k; i) { if (divisor LLONG_MAX / 10) { // 防溢出检查 divisor 0; // 或处理为越界 break; } divisor * 10; } int digit (divisor 0) ? 0 : ((safeNum / divisor) % 10); cout digit; } cout endl; } // 调用printAsFixedWidth(7, 3); // 输出 007 // 调用printAsFixedWidth(-7, 3); // 输出 -07 (注意符号位占一位)4.4 性能考量除法和取模的成本在底层整数除法和取模运算是相对昂贵的操作比加法、乘法慢得多。在需要高性能的代码中例如在紧密循环中处理大量数字频繁使用% 10和/ 10可能会成为瓶颈。优化思路查表法如果数字范围有限例如0-9999可以预计算所有数字的数位并存储在表中用空间换时间。使用编译器内置函数或位运算对于特定基数如2的幂次方2 4 8 16取模和除法可以用更快的位运算,代替。但十进制10不是2的幂所以此路不通。批量处理在有些算法中可以一次取出多位数字。例如对于一个32位整数其十进制表示最多10位。我们可以通过一次除法取出高5位和低5位分别处理但这通常需要配合较大的除法运算优化效果取决于具体场景和CPU架构。对于绝大多数应用% 10和/ 10的性能完全足够不需要过度优化。但了解其成本是有必要的。5. 从整数到字符串另一种视角和工具“输出各个数位”这个问题本质上是一个格式化输出问题。而C标准库提供了强大的格式化工具字符串流 (std::stringstream) 和字符串本身 (std::string)。5.1 使用字符串转换实现数位分离将整数转换为十进制字符串字符串中的每个字符就是对应的数位数字的字符表示。这种方法直观且不易出错。#include iostream #include string #include sstream #include algorithm // for reverse using namespace std; void printDigitsUsingString(int num) { // 使用stringstream进行转换能自动处理负号 stringstream ss; ss num; string numStr ss.str(); // 判断是否为负数 bool isNegative (!numStr.empty() numStr[0] -); string digitsPart isNegative ? numStr.substr(1) : numStr; cout num 的各位数字是: ; if (isNegative) cout (负号) ; for (char ch : digitsPart) { // 将字符数字转换为整数数字 int digit ch - 0; // 这是关键技巧字符0-9的ASCII码是连续的 cout digit ; } cout endl; } int main() { printDigitsUsingString(12345); // 1 2 3 4 5 printDigitsUsingString(-678); // (负号) 6 7 8 printDigitsUsingString(0); // 0 // 甚至可以处理超大整数如果使用string存储大数 // string hugeNum 12345678901234567890; // 遍历 hugeNum 即可得到每一位 return 0; }优势代码极其简洁不易出错。天然支持负数字符串自带“-”号。可以轻松处理前导零字符串表示“007”就是三个字符。理论上可以处理任意大的整数如果配合大数库或自定义字符串大数。劣势性能开销整数到字符串的转换本身涉及除法和取模运算在底层实现并且有动态内存分配。对于性能极度敏感的场景可能不如直接数学运算。需要理解字符到整数的转换技巧ch - 0。5.2 如何选择数学方法 vs 字符串方法这是一个常见的工程权衡。选择数学方法取模/除法当你只需要获取特定某一位的数字而不是所有位。你在编写底层、高性能的算法库需要极致性能。你正在学习或教授计算机基础原理如进制转换。处理的数据不是十进制例如二进制、十六进制位分离这时位运算更高效。选择字符串方法当你需要方便地获取所有数位并进行遍历。你的主要目的是为了显示或格式化输出。代码可读性和开发效率是首要考虑。你需要处理超过内置整数类型范围的大数这时只能用字符串或特殊的大数类来表示。个人经验在业务代码中我80%的情况会使用字符串方法。因为它更清晰更不容易在边界条件上犯错而且“将数字转为字符串进行处理”是一个非常通用的模式。只有在明确的性能热点Profiling证明这里是瓶颈或处理非十进制时我才会回归到数学方法。6. 举一反三非十进制下的数位分离我们讨论的都是十进制。但计算机世界是二进制的编程中也常接触十六进制、八进制。原理完全相同只需改变基数。核心公式通用化对于一个以base为基数的数字num其第k位从低位第0位开始的数字是digit_k (num / (base^k)) % base二进制base2示例获取一个整数的指定位int getBit(int num, int k) { // 获取第k位比特 (0为最低位) return (num k) 1; // 右移k位后与1进行位与效率极高 } // 或者用通用公式 int getBitGeneral(int num, int k) { int divisor 1 k; // 2的k次方用左移实现 return (num / divisor) % 2; }十六进制base16示例分离字节一个32位整数有8个十六进制位每个十六进制位是4个二进制位。在C中我们常用流操作符std::hex来输出十六进制字符串。但用数学方法也可以void printHexDigits(int num) { unsigned int uNum num; // 用无符号数来处理避免算术右移的符号扩展问题 cout showbase hex num 的十六进制各位是从低位到高位: ; for (int i 0; i 8; i) { // 假设32位int8个十六进制位 int digit uNum 0xF; // 取低4位即一个十六进制位 cout digit ; uNum 4; // 右移4位相当于除以16 } cout dec noshowbase endl; // 恢复十进制输出状态 } // 调用 printHexDigits(255); // 输出 0xff 的十六进制各位是: 15 15 0 0 0 0 0 0可以看到对于2的幂次方作为基数位运算 (,) 可以完美替代昂贵的%和/运算这是性能优化的一个关键点。7. 综合实战一个健壮的数位分离工具函数最后结合我们上面讨论的所有要点通用性、负数处理、INT_MIN陷阱、字符串方法的选择我提供一个我个人在项目中常用的、健壮的“获取整数十进制各位数字”的函数实现。它采用字符串方法强调正确性和易用性。#include iostream #include string #include sstream #include vector #include limits /** * brief 获取一个整数的各个十进制数位。 * param num 输入的整数 * return std::vectorint 包含从最高位到最低位数字的向量。对于0返回{0}。 * * note 此函数能正确处理所有整数范围的值包括INT_MIN。 * 使用字符串转换实现代码清晰健壮适用于大多数非极端性能要求的场景。 */ std::vectorint getDecimalDigits(int num) { std::vectorint digits; // 使用stringstream进行转换它能自动处理INT_MIN等边界情况 std::stringstream ss; ss num; std::string numStr ss.str(); // 遍历字符串跳过可能的负号 for (char ch : numStr) { if (ch -) { // 可以选择将负号以特殊形式表示或者忽略。 // 这里我们忽略负号只返回数字部分的数位。 // 如果需要包含符号信息可以修改返回类型或使用pair。 continue; } // 将字符0-9转换为整数0-9 digits.push_back(ch - 0); } // 处理输入为0的情况上面的循环会生成一个空的vector我们需要手动加入0 if (digits.empty()) { digits.push_back(0); } return digits; } /** * brief 获取一个整数的指定位十进制上的数字。 * param num 输入的整数 * param k 位置索引0表示个位1表示十位依此类推。 * return int 指定位上的数字0-9。如果该位不存在例如获取123的千位返回0。 * * note 此函数能正确处理所有整数范围的值包括INT_MIN。 * 内部使用数学方法适用于只需要某一位的场景。 */ int getDecimalDigitAt(int num, int k) { // 使用long long避免abs(INT_MIN)溢出 long long absNum llabs(static_castlong long(num)); long long divisor 1; for (int i 0; i k; i) { // 简单溢出检查如果divisor已经超过LLONG_MAX/10继续乘10会溢出。 // 此时说明请求的k位已经远远超出数字可能的最大位数直接返回0。 if (divisor std::numeric_limitslong long::max() / 10) { return 0; } divisor * 10; } // 如果数字的绝对值小于divisor说明该位为0 if (absNum divisor) { return 0; } return static_castint((absNum / divisor) % 10); } // 测试用例 int main() { // 测试getDecimalDigits std::vectorint testCases {0, 5, 123, -456, 1000, -1000, 2147483647, -2147483648}; for (int num : testCases) { auto digits getDecimalDigits(num); std::cout num - ; for (int d : digits) std::cout d ; std::cout std::endl; } std::cout \n---\n; // 测试getDecimalDigitAt int num -12345; std::cout 数字 num :\n; std::cout 个位(k0): getDecimalDigitAt(num, 0) std::endl; // 5 std::cout 十位(k1): getDecimalDigitAt(num, 1) std::endl; // 4 std::cout 百位(k2): getDecimalDigitAt(num, 2) std::endl; // 3 std::cout 千位(k3): getDecimalDigitAt(num, 3) std::endl; // 2 std::cout 万位(k4): getDecimalDigitAt(num, 4) std::endl; // 1 std::cout 十万位(k5): getDecimalDigitAt(num, 5) std::endl; // 0 return 0; }这个实战代码提供了两种风格的函数getDecimalDigits: 当你需要所有数位时使用返回一个向量清晰无坑。getDecimalDigitAt: 当你只需要特定某一位时使用高效且正确处理了溢出和边界。它们都妥善处理了INT_MIN这个“魔鬼数字”。在实际项目中将这些基础功能封装成经过充分测试的工具函数能极大提高代码的可靠性和开发效率。下次面试再被问到“输出个十百位”你完全可以从这个简单问题出发展现出对边界条件、性能取舍和工程实践的深入理解这远比单纯写对那三行代码要有价值得多。

相关新闻

微软AI算力分配策略:平衡Azure客户需求与自研业务发展

微软AI算力分配策略:平衡Azure客户需求与自研业务发展

微软作为全球科技巨头,正面临一个关键的战略抉择:在AI算力资源日益紧张的背景下,如何平衡Azure云服务客户的算力需求与自身AI自研业务的资源分配。这个决策不仅影响微软的短期股价表现,更将决定其在AI时代的长期竞争力。当前微软的…

2026/7/29 2:36:20阅读更多 →
Python游戏开发入门:用Pygame从零实现经典打砖块游戏

Python游戏开发入门:用Pygame从零实现经典打砖块游戏

1. 项目概述:为什么用Pygame做打砖块是绝佳的入门选择如果你刚开始学Python,想找个项目练手,但又觉得那些命令行工具或者数据分析的案例有点枯燥,那做个游戏绝对能让你眼前一亮。打砖块这个经典游戏,从上世纪70年代诞生…

2026/7/29 2:34:20阅读更多 →
物联网设备安全芯片SE050与PIC18F26K22应用指南

物联网设备安全芯片SE050与PIC18F26K22应用指南

1. 为什么物联网设备需要专用安全芯片?在智能家居和工业物联网项目中,开发者常面临一个两难选择:使用通用MCU实现基础功能,还是为安全特性增加专用芯片?我曾参与过一个智能电表项目,最初采用纯软件加密方案…

2026/7/29 2:34:20阅读更多 →
多雷达融合算法:从原理到工程落地的核心挑战与实战解析

多雷达融合算法:从原理到工程落地的核心挑战与实战解析

1. 从“单打独斗”到“群策群力”:为什么需要多雷达融合在自动驾驶、智能交通、安防监控这些领域,雷达早就不是什么新鲜玩意儿了。但如果你还停留在“一个雷达负责一个区域”的思维里,那可能就有点跟不上趟了。我干了十几年传感器系统集成&am…

2026/7/29 3:56:36阅读更多 →
卫星电视LNB选购指南:从双本振到噪声系数的全面解析

卫星电视LNB选购指南:从双本振到噪声系数的全面解析

1. 从“锅盖”到信号:LNB究竟是什么?如果你家里或者老家还在用卫星电视,那个架在阳台或者屋顶上的“锅盖”你一定不陌生。但你知道吗,那个“锅”本身只是个反射信号的“镜子”,真正把来自几万公里高空卫星的微弱信号“…

2026/7/29 3:56:36阅读更多 →
AI领域文献泛滥危机:为什么你读了200篇仍发不出顶刊?3个被忽略的认知带宽陷阱

AI领域文献泛滥危机:为什么你读了200篇仍发不出顶刊?3个被忽略的认知带宽陷阱

更多请点击: https://codechina.net 第一章:AI领域文献泛滥危机的本质解构 AI领域的论文产出正以前所未有的速度膨胀——arXiv上平均每日新增超400篇AI相关预印本,NeurIPS 2023投稿量达11,800,较五年前增长172%。这种“数量爆炸”…

2026/7/29 3:56:36阅读更多 →
51单片机直流电机控制:从PWM调速到H桥驱动的Proteus仿真实践

51单片机直流电机控制:从PWM调速到H桥驱动的Proteus仿真实践

1. 项目缘起:从“转起来”到“精准控制”的跨越很多刚开始接触单片机的朋友,第一个让硬件“动起来”的项目往往就是控制一个直流电机。看着小马达嗡嗡地转,那种亲手驱动物理世界的成就感,是点亮LED灯无法比拟的。但很快你就会发现…

2026/7/29 3:56:36阅读更多 →
STM32入门指南:从核心概念到开发实战,快速掌握嵌入式开发

STM32入门指南:从核心概念到开发实战,快速掌握嵌入式开发

1. 从零开始:为什么是STM32?如果你刚接触嵌入式开发,或者从51单片机、Arduino转过来,第一个问题可能就是:市面上单片机这么多,为什么偏偏要学STM32?这个问题我当年也问过自己。简单来说&#xf…

2026/7/29 3:56:35阅读更多 →
PX4解锁后禁止自动上锁参数修改

PX4解锁后禁止自动上锁参数修改

1. COM_DISARM_PRFLT -1- 遥控器解锁后- 如果 10 秒内没有满足起飞条件- PX4 会执行 预起飞自动上锁改成-1之后就不会触发了

2026/7/29 3:54:35阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/28 4:06:39阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/28 2:08:06阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/28 1:38:28阅读更多 →
28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“! 在构建复杂的 Agent 系统时,我们经常会遇到这样的场景:Agent 正在执行一个多步骤的任务,比如“下单购买商品”,但执行到一半时,我们…

2026/7/29 0:01:46阅读更多 →
自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

近日,国际专注开放式技术研发的声学品牌Nank南卡,正式官宣实力艺人曾舜晞担任品牌代言人。消息一经发出便轰动全网。为什么耳机品牌不选择流量明星、老牌歌手?而且是选择曾舜晞?让我们一起来探索一下!比起短期的流量&a…

2026/7/29 0:01:46阅读更多 →
【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:01:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/28 20:22:24阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/28 3:17:03阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/28 2:35:58阅读更多 →