<C#>如何计算天文数字

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了<C#>如何计算天文数字相关的知识,希望对你有一定的参考价值。

以前算个4的100次方都算不出来
我想知道那些天文数字是怎么计算的 用什么数据类型
比方100000001的平方
使用移位运算用String存储吗
谁能给个算法

我是这么想的:

采用科学计数法表示。

原理很简单,把Nm1和Nm2采用科学计数法表示,然后把前面的数相乘,0相加就行了。

要求高精度,那么就用Decimal来表示吧,这种数据类型精确到小数点后面28位。

以2个数相乘为例:

String result = "";
Int32 nm1WeiSu = nm1.LastIndexOf('.') - 1;
Int32 nm2WeiSu = nm2.LastIndexOf('.') - 1;
nm1 = nm1.Replace(".", "");
nm2 = nm2.Replace(".", "");

nm1 = nm1.Insert(1, ".");
nm2 = nm2.Insert(1, ".");

Decimal Num1 = Decimal.Parse(nm1);
Decimal Num2 = Decimal.Parse(nm2);

Decimal Result = Num1 * Num2 ;
result = Convert.ToString(Result);

Int32 ResultWeiSu = result.LastIndexOf('.') - 1;

result = result.Replace(".", "").Insert(1, ".");

Int32 ZongWeiSu = nm1WeiSu + nm2WeiSu*2 + ResultWeiSu;

result += " E+" + ZongWeiSu.ToString();

Console.WriteLine(result);
参考技术A 凉算,自己想办法吧,转化为255进制数组进行运算应该比用字符串速度快些,具体方法那就很复杂了

如何将第一个数字移动到c ++中数字的末尾?

【中文标题】如何将第一个数字移动到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 -&gt; 9341.

【问题讨论】:

一定要使用整数类型吗? std::stringstd::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 想要来自1234523451,而不是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_10Xdouble 更精确(例如 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 -&gt; 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 将数字向左移动并留下一个“洞”,您可以稍后根据需要进行填充。 (如果这对您来说很明显,我们深表歉意。) 您可以只使用整数运算、没有浮点数、没有函数(logexp)来完成所有这些操作。其他解决方案已经展示了完整的算法;我强调你可以不用浮点数和日志。 小心使用 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 来获得最高有效位。我们将存储这个在名为pint 中。

在这种情况下,这给了我们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#>如何计算天文数字的主要内容,如果未能解决你的问题,请参考以下文章

欧美国家划分的天文四季和我国的在具体时间上有啥差别

人工智能助力天文观测分析海量数据已十分普遍

天文学图Vue应用

天文认识星空之观星术纵横

CTutorial C 03 数据类型变量

格林尼治天文台和中国时差?