如何将第一个数字移动到c ++中数字的末尾?
Posted
技术标签:
【中文标题】如何将第一个数字移动到c ++中数字的末尾?【英文标题】:How to move the first digit to the end of a number in c++? 【发布时间】:2018-02-02 13:49:01 【问题描述】:代码如下:
#include <iostream>
using namespace std;
int main ()
int n;
cin >> n;
int first = n;
while (first>=10)
first/=10;
cout << first << endl;
在上面的代码中,我试图获取一个正数的第一个数字,我想做的是把它放在最后一个数字之后,例如:
1934 -> 9341
.
【问题讨论】:
一定要使用整数类型吗?std::string
和 std::rotate
让这一切变得非常简单。
@MichaëlvanderHaven 不是真的,因为 OP 不想交换数字。
它不会先与最后交换,如果是这样,1934 将是 4931
@DerekCole 我不得不问——如果你不能先在纸上弄清楚,为什么还要写代码?
@Ron 是的,这不是重复的。第一个问题是1234
怎么办-->4231
,这个问怎么办1234
-->2341
【参考方案1】:
使用std::to_string将数字转换为字符串,使用std::rotate执行左旋转并使用std::stoull函数转换回数字:
std::string s = std::to_string(n);
std::rotate(s.begin(), s.begin() + 1, s.end());
n = std::stoull(s);
包含所有标题:
#include <iostream>
#include <string>
#include <algorithm>
int main()
unsigned long long n = 1934;
std::string s = std::to_string(n);
std::rotate(s.begin(), s.begin() + 1, s.end()); // left rotation
n = std::stoull(s);
std::cout << n; // 9341
【讨论】:
OP 想要来自12345
的23451
,而不是52341
。
@Ron 逻辑很好 :-)【参考方案2】:
这是一个不使用字符串或浮点函数/算术的简单解决方案。使用pow()
等函数可能会遇到in this question 所述的问题。
#include <iostream>
int main()
unsigned long long n = 1934L;
// save the original
unsigned long long final_number = n;
// multiplying factor
unsigned long long mult = 1;
// start by making sure we do not loop one too many times to
// calculate the multiplier
n /= 10;
while (n > 0)
// determines the multiplication factor after the loop
mult *= 10;
// strip off digit from number
n /= 10;
// create the final number from the original and the multiplication factor
final_number = (final_number % mult) * 10 + final_number / mult;
std::cout << final_number << "\n";
Live Example
基本上我们通过循环计算多少位数,同时将乘数增加10。然后在循环之后,使用模数、乘法、除法和加法来构造数字。
例如,在循环之后,final_number
将是
(1934 % 1000) * 10 + 1934 / 1000 =
934 * 10 + 1934 / 1000 =
9340 + 1934 / 1000 =
9340 + 1 =
9341
注意:我查看了生成的汇编语言here,很惊讶编译器能够弄清楚代码的意图,并在编译时计算出 9341。我怀疑pow
解决方案或浮点方法会产生这些结果。
【讨论】:
小角限制:(final_number % mult) * 10
可能溢出。
mult
类型应该匹配 final_number
类型。【参考方案3】:
您可以修改循环以不仅获取第一位数字,还可以同时计算位数(这是循环的迭代次数)。然后,酌情使用%
和* 10
修改n
。
【讨论】:
【参考方案4】:假设我们有正整数作为输入。
获取最重要的数字
MSD=floor(X/pow(10,floor(log10(X))));
获取剩余的数字
Rest=X%pow(10,floor(log10(X)));
将其余部分提高到适当的值
Rest=Rest*10;
添加前一个最重要的数字
Y=Rest+MSD.
分解示例:
X=54321; // 54321
log10(X) // 4.734...
floor(... ) // 4
pow(10,... ) // 10000
X/... // 5.4321
MSD=floor(... );// 5
pow(10,floor(log10(X)) // 10000
X%... // 4321
10*... // 43210
Y=MSD+... ; // 43215
【讨论】:
呃,不是^
Bitwise XOR吗?你的意思是使用pow()
?
@Drise 感谢您的指出。我习惯了不同的语言。此外,正如 Phillip Schmid 使用的那样,基于 C 的语言默认情况下会转换整数,因此不需要 floor()
,但我将其用作独立于语言的答案。 ^
是 MATLAB 中的强大功能,我主要使用的是...
实际上,如果我没记错的话,“向下舍入整数 [除]”不是您在 C/C++ 中寻找的内容,它是 truncation towards zero
MSD=floor(X/pow(10,floor(log10(X))));
在数学上是正确的,但在 X
的值接近 D * some_power_of_10
或 X
比 double
更精确(例如 64 位)时,计算上容易出现舍入错误.【参考方案5】:
我首先要说我不是 C++ 程序员。所以我并不是说这段代码很好,只是它可以工作并且遵循你的方法!
在向您展示代码的最小编辑以获得您想要的内容之前,我将引导您完成操作,并举例说明:我们假设您要将 2345
转换为 3452
n
) 的最高有效数字 (first
) 开始
您现在需要从前面删除该数字。这很简单:
我们已经有一个循环,我们将 first
除以 10,所以让我们重用它
创建一个从 1 开始的数字(我们称之为 bigness
),然后在每个循环中将其乘以 10。
您现在有 3 个号码:
n
= 2345
first
= 2
bigness
= 1000
这就是你所需要的!
你可以从n
中减去first * bigness
来去掉前面的数字——345
您可以将其乘以 10
并添加 first
以将数字放在末尾 - 3452
这是结束代码:
#include <iostream>
using namespace std;
int main ()
int n;
cin >> n;
int first = n;
int bigness = 1;
while (first >= 10)
first /= 10;
bigness *= 10;
n = n - (first * bigness);
n = (n * 10) + first;
cout << n;
请注意,这会给像20000
这样的数字留下问题——它们变成2,因为我们的代码不知道我们想要00002
。使用 printf
之类的东西来维护位数很容易解决这个问题,但这意味着循环中的另一个变量,从 1 开始,计算我们需要的位数。
【讨论】:
(n * 10) + first;
可能会溢出像n = 1987654321
这样的起始值。
是的 - 使用整数的缺点。正如我在第一行中提到的,我并不是说它是好的代码 - 只是它从 OP 的起点在逻辑上遵循。我很确定这对于大量意外输入(至少可以说是负数、小数和非数字输入)会严重失败。【参考方案6】:
由于 C++ 整数最多有十几个数字,代码可以使用简单的递归解决方案:
unsigned reverse_helper(unsigned x)
if (x < 10)
return x;
unsigned last = reverse_helper(x/10);
cout << x%10;
return last;
void reverse(unsigned x)
cout << reverse_helper(x)) << endl;
测试代码
int main(void)
reverse(0);
reverse(9);
reverse(10);
reverse(1934);
reverse(1234567890);
0
9
01
9341
2345678901
【讨论】:
【参考方案7】:不使用字符串的解决方案。它确实使用了std::stack
,它可能不会获得任何效率奖,但它应该非常简单易懂。
#include <stack>
#include <iostream>
int main()
int num = 1934;
std::stack<int> digits;
// Break the number into digits, pushing them onto a stack
while (num)
auto digit = num % 10;
digits.push(digit);
num /= 10;
// Get the first digit from the top of the stack and save it
auto first = 0;
if (!digits.empty())
first = digits.top();
digits.pop();
// Pop the remaining digits off the stack and print them
while (!digits.empty())
std::cout << digits.top();
digits.pop();
// Print the first digit on the end
std::cout << first << '\n';
编辑:修复了 num == 0
的错误。请注意,负数处理不正确,但我不确定这种情况下所需的行为是什么。使用unsigned
代替int
可能是个好主意。
【讨论】:
num == 0
时,digits.top();
是否可靠地返回 0?
@chux:不,它非常可靠地调用了未定义的行为。它也不适用于负数。
@chux:现在应该修复了。感谢代码审查!
替代方案:while (num) auto digit = num % 10; digits.push(digit); num /= 10;
--> do auto digit = num % 10; digits.push(digit); num /= 10; while (num);
确保堆栈中至少有一个。那么if (!digits.empty())
就不需要了。【参考方案8】:
这是一个不使用字符串的版本。
//There's also a builtin log10 function but you can write your own if you want to:
int log10(int nbr)
return log(n) / log(10);
//....
int first_digit = n / (int)pow(10, log10(n));
int everything_else = n % (int)pow(10, log10(n));
确保包含math.h
它使用了 float -> int
转换在 C++ 中总是向零舍入这一事实。所以(int)log10(101)
将返回 2,因此pow(10, (log10(n)))
将舍入每个向下舍入到10/100/1000/etc
的数字。剩下的只是简单的除法和取模。
【讨论】:
我已经添加了一条评论,如果这是您的批评,那么还有一个内置的log10
函数。如果这不是你的意思,请详细说明。该解决方案应该比使用字符串的任何答案都快很多
也许将 pow() 包装在 floor() 中只是为了使其明确?
log(n)
和 log(10)
返回真实数学 log 的近似数学结果。将超越函数(如log(), exp()
)的结果转换为int
可能会从x.9999999999999...
意外返回int
【参考方案9】:
这是编程和数学+编程竞赛的典型元素,所以我不会给出完整的答案,但我会说:
几乎可以肯定,使用字符串不是最节省 CPU 时间的解决方案。 您已经有了第一个(最重要的)数字。修改问题中的代码,您可以计算 10 的适当幂以从原始数字中减去第一位数字。 请注意,n * 10
将数字向左移动并留下一个“洞”,您可以稍后根据需要进行填充。 (如果这对您来说很明显,我们深表歉意。)
您可以只使用整数运算、没有浮点数、没有函数(log
、exp
)来完成所有这些操作。其他解决方案已经展示了完整的算法;我强调你可以不用浮点数和日志。
小心使用 0 和负数。
【讨论】:
【参考方案10】:由于std::string
已经有很多解决方案,我尝试不使用它,这是我的结果。
我希望这会有所帮助。
#include <iostream>
#include <cmath>
using namespace std;
int removeFirst(int n)
int tmp(0);
for (int i(0);; ++i)
int m = n % 10;
n /= 10;
if (n != 0)
tmp += pow(10, i) * m;
else
break;
return tmp;
int main()
int input, first, withoutFirst;
cin >> input;
withoutFirst = removeFirst(input);
while (input >= 10)
input /= 10;
first = input;
cout << withoutFirst << first << endl;
帮助使用:trying to remove first digit of any number
问候。
【讨论】:
问题是数字不应该颠倒,只是最左边的数字移动到最右边的数字。 @PaulMcKenzie 我明白了,我要更改代码。谢谢,没看到。 另外,已经有两种字符串的解决方案了,这个问题不用字符串也可以解决。 @PaulMcKenzie 是的,这是一个没有字符串的解决方案。 除了作为练习之外,我不明白为什么人们更愿意在循环中使用std::pow
而不是std::to_string
+std::stoull
。迭代浮点运算通常比将整数转换为字符串并返回要慢得多。【参考方案11】:
string
已经有一些答案,到目前为止还有一个答案没有string
。使用string
是最有效的一种。但是,如果 OP 想通过计算方法和使用整数来解决它,这就是我尝试过的。当不使用string
时,我猜这种解决方案效率更高。
#include <iostream>
#include <math.h>
using namespace std;
int main ()
int n, digits, firstDigit, firstDigitToLast;
cin >> n;
digits = (int)log10(n);
firstDigit = (int)(n / pow(10, digits));
firstDigitToLast = n % ((int) pow(10, digits));
firstDigitToLast *= 10;
firstDigitToLast += firstDigit;
cout << firstDigitToLast << endl;
【讨论】:
【参考方案12】:std::string s = std::to_string(n);
s += s.front();
s.erase(0, 1);
n = std::stoull(s);
这个:
-
将数字转换为字符串。
将第一个字符添加到末尾。
删除第一个字符。
并将结果转换回
unsigned long long
。
Live Example
【讨论】:
【参考方案13】:我会使用log10
和%
。
int num = 8907;
int num_digits = log10(num); // Value of 3 for 8907
int pwr = pow(10, num_digits); // Value of 1000 for 8907
int ones_place = num % 10; // 7
int bigs_place = num / pwr; // 8
int cur_msd = bigs_place * pwr; // 8000
int new_msd = ones_place * pwr; // 7000
num -= cur_msd;
num += new_msd;
num -= ones_place;
num += bigs_place;
cout << num << endl;
此代码为我输出 7908。
编辑
我看错了帖子。我以为你想要交换 LSB 和 MSB,而不是旋转。
将最后 4 行替换为
num -= cur_msd;
num *= 10;
num += bigs_place;
【讨论】:
【参考方案14】:虽然循环和字符串可能非常有效,但在这种情况下它们是完全没有必要的。 你只需要一点数学:
#include <math.h> // log10, pow, floor
#include <stdio.h> // printf
int main ()
int n = 6945;
int p = pow(10,floor(log10(n)));
int output = (n - ((n/p)%10)*p)*10+((n/p)%10);
printf("%i",output); // outputs 9456
这个想法是首先找到数字有多少位 (floor(log10(n))
),然后通过将输入除以 10 的幂 (pow(10,floor(log10(n)))
) 模 10 来获得最高有效位。我们将存储这个在名为p
的int
中。
在这种情况下,这给了我们6
。然后我们从n
中减去6
乘以p
得到剩余的数字(在我们的例子中为945
),然后我们将其乘以十并加上6
,得到我们的最终答案9456
【讨论】:
【参考方案15】:这就是我的做法
#include<stdio.h>
#include<math.h>
int main()
int a,g=10,m=1,c,num;
printf("enter the number : ");
scanf("%d",&a);
c=log10(a);
num=num+((a%10)*pow(10,c));
a=a/10;
c=log10(a);
while(m<=c)
if(m==c)
num=num+((a%10)*g)+a/10;
break;
else
num=num+((a%10)*g);
g=g*10;
a=a/10;
m=m+1;
printf("%d",num);
【讨论】:
以上是关于如何将第一个数字移动到c ++中数字的末尾?的主要内容,如果未能解决你的问题,请参考以下文章
C语言从TXT文档中读取一组数字时如何判断已经读到最后一个数字?