在c#中需要一个数据类型来容纳100万以上的数字
本文关键字:数据类型 数字 万以上 一个 | 更新日期: 2023-09-27 17:53:55
我正在用c#计算PI,到目前为止它是完美的,除了我的数据类型限制了我。如果我使用double,我得到如下结果:
k=0, δ =3,14176587301587, pi=3,14176587301587
k=1, δ =-0,000173301147482709, pi=3,14159257186839
k=2, δ = 8,17736604635702e -08, pi=3,14159265364205
k=3, δ =- 5,22954018637708e -11, pi=3,14159265358975
k=4, δ = 3,78997628626364e -14, pi=3,14159265358979
k=5, δ =- 2,94045250629684e -17, pi=3,14159265358979
你可能注意到,在我第四次运行时,我的数字已经达到最大值。小数只对稍微多一点有帮助,但我需要很多。我的算法循环和添加。
我想使用字符串,但我的问题是,如果我没有一个数据类型来保存这些数字我怎么把它们变成一个字符串?
我知道以前有人这样做过,我只是想知道如何……
谢谢你的建议!
您可以使用来自CodeProject的Swensen.BigInt.dll程序集。如果你需要。net 2.0版本,你可以在这里下载。
您可以使用BigInteger来存储小数点之后的所有内容。
使用这段代码,它就像一个魅力
using System;
using System.Text;
class Solution
{
static void Main(string[] args)
{
BigNumber x = new BigNumber(100);
BigNumber y = new BigNumber(100);
x.ArcTan(16, 5);
y.ArcTan(4, 239);
x.Subtract(y);
stopWatch.Stop();
Console.WriteLine(x.Print());
Console.ReadLine();
}
}
public class BigNumber {
private UInt32[] number;
private int size;
private int maxDigits;
public BigNumber(int maxDigits) {
this.maxDigits = maxDigits;
this.size = (int) Math.Ceiling((float)maxDigits * 0.104) + 2;
number = new UInt32[size];
}
public BigNumber(int maxDigits, UInt32 intPart)
: this(maxDigits) {
number[0] = intPart;
for (int i = 1; i < size; i++) {
number[i] = 0;
}
}
private void VerifySameSize(BigNumber value) {
if (Object.ReferenceEquals(this, value))
throw new Exception("BigNumbers cannot operate on themselves");
if (value.size != this.size)
throw new Exception("BigNumbers must have the same size");
}
public void Add(BigNumber value) {
VerifySameSize(value);
int index = size - 1;
while (index >= 0 && value.number[index] == 0)
index--;
UInt32 carry = 0;
while (index >= 0) {
UInt64 result = (UInt64)number[index] +
value.number[index] + carry;
number[index] = (UInt32)result;
if (result >= 0x100000000U)
carry = 1;
else
carry = 0;
index--;
}
}
public void Subtract(BigNumber value) {
VerifySameSize(value);
int index = size - 1;
while (index >= 0 && value.number[index] == 0)
index--;
UInt32 borrow = 0;
while (index >= 0) {
UInt64 result = 0x100000000U + (UInt64)number[index] - value.number[index] - borrow;
number[index] = (UInt32)result;
if (result >= 0x100000000U)
borrow = 0;
else
borrow = 1;
index--;
}
}
public void Multiply(UInt32 value) {
int index = size - 1;
while (index >= 0 && number[index] == 0)
index--;
enter code here
UInt32 carry = 0;
while (index >= 0) {
UInt64 result = (UInt64)number[index] * value + carry;
number[index] = (UInt32)result;
carry = (UInt32)(result >> 32);
index--;
}
}
public void Divide(UInt32 value) {
int index = 0;
while (index < size && number[index] == 0)
index++;
UInt32 carry = 0;
while (index < size) {
UInt64 result = number[index] + ((UInt64)carry << 32);
number[index] = (UInt32) (result / (UInt64)value);
carry = (UInt32)(result % (UInt64)value);
index++;
}
}
public void Assign(BigNumber value) {
VerifySameSize(value);
for (int i = 0; i < size; i++) {
number[i] = value.number[i];
}
}
public string Print() {
BigNumber temp = new BigNumber(maxDigits);
temp.Assign(this);
StringBuilder sb = new StringBuilder();
sb.Append(temp.number[0]);
sb.Append(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator);
int digitCount = 0;
while (digitCount < maxDigits) {
temp.number[0] = 0;
temp.Multiply(100000);
sb.AppendFormat("{0:D5}", temp.number[0]);
digitCount += 5;
}
return sb.ToString();
}
public bool IsZero() {
foreach (UInt32 item in number) {
if (item != 0)
return false;
}
return true;
}
public void ArcTan(UInt32 multiplicand, UInt32 reciprocal) {
BigNumber X = new BigNumber(maxDigits, multiplicand);
X.Divide(reciprocal);
reciprocal *= reciprocal;
this.Assign(X);
BigNumber term = new BigNumber(maxDigits);
UInt32 divisor = 1;
bool subtractTerm = true;
while (true) {
X.Divide(reciprocal);
term.Assign(X);
divisor += 2;
term.Divide(divisor);
if (term.IsZero())
break;
if (subtractTerm)
this.Subtract(term);
else
this.Add(term);
subtractTerm = !subtractTerm;
}
}
}