递归函数实现长字符串转整数出错问题咨询(C++)
Let's break down the problem first, then walk through a proper recursive solution.
What's Causing the Negative Output?
Your test string "123456789101" translates to the number 123456789101, which is way larger than the maximum value a standard 32-bit int can hold (that's 2147483647, or ~2.1 billion). When you try to store a number beyond an integer type's limit, you hit integer overflow—the value wraps around according to two's complement rules, resulting in a negative number.
On top of that, using double as an intermediate storage is risky: while double has a larger range, it's a floating-point type that loses precision for integers with more than 15-17 digits. Even if you avoided overflow, this could introduce subtle errors in your conversion.
A Proper Recursive Solution for Long Strings
First, switch to a larger integer type like long long (64-bit, max value ~9e18, which easily handles your test string). Then, rewrite the recursive logic to avoid floating-point functions like pow—instead, use integer arithmetic directly, which is both faster and more reliable.
Option 1: Straightforward Recursive Conversion
This version works by recursively processing the substring starting from the second character, then combining it with the first digit multiplied by the appropriate power of 10:
#include <iostream> #include <string> using namespace std; long long stringToLongLong(const string& str) { // Base case: single character, return its numeric value if (str.size() == 1) { return str[0] - '0'; } // Recursively convert the substring without the first character long long subResult = stringToLongLong(str.substr(1)); // Get the numeric value of the first character int firstDigit = str[0] - '0'; // Calculate 10^(length-1) using integer arithmetic (no floating-point!) long long power = 1; for (int i = 0; i < str.size() - 1; ++i) { power *= 10; } return firstDigit * power + subResult; } int main() { string s1 = "12345"; string s2 = "123456789101"; cout << "s1: " << stringToLongLong(s1) << endl; cout << "s2: " << stringToLongLong(s2) << endl; return 0; }
Option 2: Optimized Recursion (Avoid Repeated Power Calculations)
The above works, but calculating the power of 10 every time adds redundant work. We can optimize this by passing a multiplier through the recursive helper function, which tracks the current digit's weight:
#include <iostream> #include <string> using namespace std; long long convertHelper(const string& str, int pos, long long multiplier) { // Base case: we've processed all characters if (pos == str.size()) { return 0; } int currentDigit = str[pos] - '0'; // Recurse on the next character, with a smaller multiplier return currentDigit * multiplier + convertHelper(str, pos + 1, multiplier / 10); } long long stringToLongLong(const string& str) { // Calculate the initial multiplier (10^(length-1)) long long multiplier = 1; for (int i = 0; i < str.size() - 1; ++i) { multiplier *= 10; } return convertHelper(str, 0, multiplier); } int main() { string s1 = "12345"; string s2 = "123456789101"; cout << "s1: " << stringToLongLong(s1) << endl; cout << "s2: " << stringToLongLong(s2) << endl; return 0; }
Handling Even Longer Strings (Beyond 64-bit Limits)
If your strings have more than 18 digits (exceeding long long's capacity), you'll need to implement big integer handling—since no native integer type can hold those values. For a recursive approach, you can store the result in a vector<int> (each element represents a digit) or build a string representation, then implement arithmetic operations for addition and multiplication by 10 recursively.
内容的提问来源于stack exchange,提问作者Maryam

