1000 digit number in C# - c#
I am working on Project Euler and ran into an issue.
I am unable to use a 1000 digit number and wanted to know if I am doing something wrong or am just going about this solution in the wrong way and if so what would be best approach be?
C#
namespace ToThePowerOf
{
class Program
{
static void Main(string[] args)
{
BigInteger n = 1;
int x = 0;
BigInteger [] number;
number = new BigInteger[149194];
number[x] = 1;
number[x + 1] = 1;
x = 3; ;
BigInteger check = 10000000000000000000000000000
0000000000000000000000000000000
0000000000000000000000000000000
0000000000000000000000000000000
0000000000000000000000000000000
0000000000000000000000000000000
0000000000000000000000000000000
0000000000000000000000000000000
0000000000000000000000000000000
00000000000000000000000;
for (int i = 99; i > 0; i--)
{
n = (n - 1) + (n - 2);
number[x] = n;
x++;
if (n > check)
{
Console.WriteLine(x);
}
}
}
}
}
I'm guessing the 'issue' you ran into (would be helpful to include error message) is that the compiler doesn't like the integer literal with 1000 digits so you can't initialise it with a very large integer literal. As others have noted, breaking the integer literal into multiple lines isn't valid either.
The number[x] = 1; lines work because the compiler can handle the integer literal 1 and because we're assigning it to a BigInteger it uses BigInteger's implicit operator to convert it to a BigInteger.
One simple method to get around your problem with the big integer literal is to use the BigInteger.Parse method to create your 1000 digit number.
BigInteger check = BigInteger.Parse("10000....", CultureInfo.InvariantCulture);
Another method could be to initialise it with a small int, then use maths to get to the number you want, as in Jon Skeet's answer.
There's no literal support for BigInteger in C#. So while using BigInteger isn't incorrect, you'll need to work out a different way of instantiating it - e.g. new BigInteger(10).Pow(1000).
Such a big literal isn't possible. Integer literals can be at most 64 bits.
To get a large biginteger, you can either convert from string, or calculate the number instead of hardcoding it. In your case calculating it with BigInteger.Pow(10, digits) is the cleanest solution.
I'm still unsure on the BigInteger handling in C#, however on the Project Euler question you refer to. You can read the number in letter by letter from a text file and convert to an int. Then do the multiplications and checks. Not elegant but it works!
See http://msdn.microsoft.com/en-us/library/system.io.filestream.aspx for syntax ref.
I'm probably really late on this, but what I did was take every number and make it a separate object within an array. I then took the first 5 numbers of the array and multiplied them together and set them to a variable. If they were greater than the max, I set it to the max. I then went on to the next set for numbers 1-6 and did the same etc. I did get an out of range exception. In which case you use a try and get format until you receive this exception. If you want to see the code, I will edit my response, but to save you time on the array, if you still want to attempt this, I will give you the array.
long[] a;
a = new long[] {
7,3,1,6,7,1,7,6,5,3,1,3,3,0,6,2,4,9,1,9,2,2,5,1,1,9,6,7,4,4,2,6,5,7,4,7,4,2,3,5,5,3,4,9,1,9,4,9,3,4,
9,6,9,8,3,5,2,0,3,1,2,7,7,4,5,0,6,3,2,6,2,3,9,5,7,8,3,1,8,0,1,6,9,8,4,8,0,1,8,6,9,4,7,8,8,5,1,8,4,3,
8,5,8,6,1,5,6,0,7,8,9,1,1,2,9,4,9,4,9,5,4,5,9,5,0,1,7,3,7,9,5,8,3,3,1,9,5,2,8,5,3,2,0,8,8,0,5,5,1,1,
1,2,5,4,0,6,9,8,7,4,7,1,5,8,5,2,3,8,6,3,0,5,0,7,1,5,6,9,3,2,9,0,9,6,3,2,9,5,2,2,7,4,4,3,0,4,3,5,5,7,
6,6,8,9,6,6,4,8,9,5,0,4,4,5,2,4,4,5,2,3,1,6,1,7,3,1,8,5,6,4,0,3,0,9,8,7,1,1,1,2,1,7,2,2,3,8,3,1,1,3,
6,2,2,2,9,8,9,3,4,2,3,3,8,0,3,0,8,1,3,5,3,3,6,2,7,6,6,1,4,2,8,2,8,0,6,4,4,4,4,8,6,6,4,5,2,3,8,7,4,9,
3,0,3,5,8,9,0,7,2,9,6,2,9,0,4,9,1,5,6,0,4,4,0,7,7,2,3,9,0,7,1,3,8,1,0,5,1,5,8,5,9,3,0,7,9,6,0,8,6,6,
7,0,1,7,2,4,2,7,1,2,1,8,8,3,9,9,8,7,9,7,9,0,8,7,9,2,2,7,4,9,2,1,9,0,1,6,9,9,7,2,0,8,8,8,0,9,3,7,7,6,
6,5,7,2,7,3,3,3,0,0,1,0,5,3,3,6,7,8,8,1,2,2,0,2,3,5,4,2,1,8,0,9,7,5,1,2,5,4,5,4,0,5,9,4,7,5,2,2,4,3,
5,2,5,8,4,9,0,7,7,1,1,6,7,0,5,5,6,0,1,3,6,0,4,8,3,9,5,8,6,4,4,6,7,0,6,3,2,4,4,1,5,7,2,2,1,5,5,3,9,7,
5,3,6,9,7,8,1,7,9,7,7,8,4,6,1,7,4,0,6,4,9,5,5,1,4,9,2,9,0,8,6,2,5,6,9,3,2,1,9,7,8,4,6,8,6,2,2,4,8,2,
8,3,9,7,2,2,4,1,3,7,5,6,5,7,0,5,6,0,5,7,4,9,0,2,6,1,4,0,7,9,7,2,9,6,8,6,5,2,4,1,4,5,3,5,1,0,0,4,7,4,
8,2,1,6,6,3,7,0,4,8,4,4,0,3,1,9,9,8,9,0,0,0,8,8,9,5,2,4,3,4,5,0,6,5,8,5,4,1,2,2,7,5,8,8,6,6,6,8,8,1,
1,6,4,2,7,1,7,1,4,7,9,9,2,4,4,4,2,9,2,8,2,3,0,8,6,3,4,6,5,6,7,4,8,1,3,9,1,9,1,2,3,1,6,2,8,2,4,5,8,6,
1,7,8,6,6,4,5,8,3,5,9,1,2,4,5,6,6,5,2,9,4,7,6,5,4,5,6,8,2,8,4,8,9,1,2,8,8,3,1,4,2,6,0,7,6,9,0,0,4,2,
2,4,2,1,9,0,2,2,6,7,1,0,5,5,6,2,6,3,2,1,1,1,1,1,0,9,3,7,0,5,4,4,2,1,7,5,0,6,9,4,1,6,5,8,9,6,0,4,0,8,
0,7,1,9,8,4,0,3,8,5,0,9,6,2,4,5,5,4,4,4,3,6,2,9,8,1,2,3,0,9,8,7,8,7,9,9,2,7,2,4,4,2,8,4,9,0,9,1,8,8,
8,4,5,8,0,1,5,6,1,6,6,0,9,7,9,1,9,1,3,3,8,7,5,4,9,9,2,0,0,5,2,4,0,6,3,6,8,9,9,1,2,5,6,0,7,1,7,6,0,6,
0,5,8,8,6,1,1,6,4,6,7,1,0,9,4,0,5,0,7,7,5,4,1,0,0,2,2,5,6,9,8,3,1,5,5,2,0,0,0,5,5,9,3,5,7,2,9,7,2,5,
7,1,6,3,6,2,6,9,5,6,1,8,8,2,6,7,0,4,2,8,2,5,2,4,8,3,6,0,0,8,2,3,2,5,7,5,3,0,4,2,0,7,5,2,9,6,3,4,5,0
};
Related
Factorial calculator presenting a negative number that should be positive. How to Fix?
I need to code a factorial calculator that goes as high as 20! I get to 19 and it's fine, but when I try to calculate 20! it returns a negative number. How can I fix this? Now, a bit of background (in case what I have is completely incorrect) I did not take the VB.Net class (where they learned factorials) so I have legit NO CLUE what I'm doing here. public partial class Form1 : Form { private void btnCalculate_Click(object sender, EventArgs e) { int f = 1, n, i; n = Int32.Parse(txtNumber.Text); for (i = 1; i <= n; i++) { f = f * i; txtFactorial.Text = f.ToString(); } } } Expected: 20! = 2,432,902,008,176,640,000 Actual: 20! = -2102132736
For large numbers you can use BigInteger struct.
The type int is too small when you're dealing with this big numbers. With the type int you can represent a maximum value of 2,147,483,647, but you want to store a more than 1B times bigger number (this is why it overflows and you get an incorrect negative number - read integer overflow). You'll need the type long for this calculation. It's enough for 20!, but if you work with even bigger numbers then use BigInteger. I get to 19 and it's fine You should check that value again. Returning a positive number doesn't mean it's correct. I'm pretty sure with int you get an incorrect value at 19! too.
How to carry number from decimal to whole byte array
Note: This is more of a logic/math problem than a specific C# problem. I have my own class called Number - it very simply contains two separate byte arrays called Whole and Decimal. These byte arrays each represent essentially an infinitely large whole number, but, when put together the idea is that they create a whole number with a decimal part. The bytes are stored in a little-endian format, representing a number. I'm creating a method called AddNumbers which will add two of these Numbers together. This method relies on another method called PerformAdd, which just adds two arrays together. It simply takes in a pointer to the final byte array, a pointer to one array to add, and a pointer to the second array to add - as well as the length of each of them. The two arrays are just named "larger" and "smaller". Here is the code for this method: private static unsafe void PerformAdd(byte* finalPointer, byte* largerPointer, byte* smallerPointer, int largerLength, int smallerLength) { int carry = 0; // Go through all the items that can be added, and work them out. for (int i = 0; i < smallerLength; i++) { var add = *largerPointer-- + *smallerPointer-- + carry; // Stick the result of this addition in the "final" array. *finalPointer-- = (byte)(add & 0xFF); // Now, set a carry from this. carry = add >> 8; } // Now, go through all the remaining items (which don't need to be added), and add them to the "final" - still working with the carry. for (int i = smallerLength; i < largerLength; i++) { var wcarry = *largerPointer-- + carry; // Stick the result of this addition in the "final" array. *finalPointer-- = (byte)(wcarry & 0xFF); // Now, set a carry from this. carry = wcarry >> 8; } // Now, if we have anything still left to carry, carry it into a new byte. if (carry > 0) *finalPointer-- = (byte)carry; } This method isn't where the problem lies - the problem is with how I use it. It's the AddNumbers method that uses it. The way it works is fine - it organizes the two separate byte arrays into the "larger" (larger meaning having a higher length of bytes) and "smaller". And then it creates pointers, it does this both for Whole and Decimal separately. The problem is with the decimal part. Let's say we're adding the numbers 1251 and 2185 together, in this situation you would get 3436 - so that works perfectly! Take another example as well: You have the numbers 4.6 and add 1.2 - once again, this works fine, and you get 5.8. The problem comes with the next example. We have 15.673 and 1.783, you would expect 17.456, however, actually, this returns: 16.1456, and the reason for that is because it doesn't carry the "1". So, this is my problem: How would I implement a way that knows when and how to do this? Here's the code for my AddNumbers method: public static unsafe Number AddNumbers(Number num1, Number num2) { // Store the final result. Number final = new Number(new byte[num1.Whole.Length + num2.Whole.Length], new byte[num1.Decimal.Length + num2.Decimal.Length]); // We're going to figure out which number (num1 or num2) has more bytes, and then we'll create pointers to smallest and largest. fixed (byte* num1FixedWholePointer = num1.Whole, num1FixedDecPointer = num1.Decimal, num2FixedWholePointer = num2.Whole, num2FixedDecPointer = num2.Decimal, finalFixedWholePointer = final.Whole, finalFixedDecimalPointer = final.Decimal) { // Create a pointer and figure out which whole number has the most bytes. var finalWholePointer = finalFixedWholePointer + (final.Whole.Length - 1); var num1WholeLarger = num1.Whole.Length > num2.Whole.Length ? true : false; // Store the larger/smaller whole number lengths. var largerLength = num1WholeLarger ? num1.Whole.Length : num2.Whole.Length; var smallerLength = num1WholeLarger ? num2.Whole.Length : num1.Whole.Length; // Create pointers to the whole numbers (the largest amount of bytes and smallest amount of bytes). var largerWholePointer = num1WholeLarger ? num1FixedWholePointer + (num1.Whole.Length - 1) : num2FixedWholePointer + (num2.Whole.Length - 1); var smallerWholePointer = num1WholeLarger ? num2FixedWholePointer + (num2.Whole.Length - 1) : num1FixedWholePointer + (num1.Whole.Length - 1); // Handle decimal numbers. if (num1.Decimal.Length > 0 || num2.Decimal.Length > 0) { // Create a pointer and figure out which decimal has the most bytes. var finalDecPointer = finalFixedDecimalPointer + (final.Decimal.Length - 1); var num1DecLarger = num1.Decimal.Length > num2.Decimal.Length ? true : false; // Store the larger/smaller whole number lengths. var largerDecLength = num1DecLarger ? num1.Decimal.Length : num2.Decimal.Length; var smallerDecLength = num1DecLarger ? num2.Whole.Length : num1.Decimal.Length; // Store pointers for decimals as well. var largerDecPointer = num1DecLarger ? num1FixedDecPointer + (num1.Decimal.Length - 1) : num2FixedDecPointer + (num2.Decimal.Length - 1); var smallerDecPointer = num1DecLarger ? num2FixedDecPointer + (num2.Decimal.Length - 1) : num1FixedDecPointer + (num1.Decimal.Length - 1); // Add the decimals first. PerformAdd(finalDecPointer, largerDecPointer, smallerDecPointer, largerDecLength, smallerDecLength); } // Add the whole number now. PerformAdd(finalWholePointer, largerWholePointer, smallerWholePointer, largerLength, smallerLength); } return final; }
The format you selected is fundamentally hard to use and I'm not aware of anyone who uses the same format for this task. For example, multiplication or division in that format must be very hard to implement. Actually I don't think you store enough information to uniquely restore the value in the first place. How in your format stored representations are different for 0.1 and 0.01? I don't think you can distinguish those two values. The issue you are facing is a lesser side-effect of the same problem: you store binary representations for decimal values and expect to be able to imply unique size (number of digits) of the decimal representation. You can't do it because when decimal overflow happens you are not guaranteed to get an overflow in your 256-based stored value as well. Actually it is more often not to happen simultaneously. I don't think you can resolve this issue in any other way than explicitly storing something equivalent to the number of digits after the decimal point. And if you are going to do that anyway, why not switch to a much simpler format of a single BigInteger (yes, it is a part of the standard library although there is nothing like BigDecimal) and a scale? This is the format used by many similar libraries. In that format 123.45 is stored as pair of 12345 and -2 (for decimal position) while 1.2345 is stored as a pair of 12345 and -4. Multiplication in that format is almost a trivial task (given that BigInteger already implements multiplication, so you just need to be able to truncate zeros at the end). Addition and subtraction are less trivial but what you need is first match the scales of the two numbers using multiplication by 10, then use standard addition over BigInteger and then normalize back (remove zeros at the end). Division is still hard and you have to decide what rounding strategies you want support because division of two numbers is not guaranteed to fit into a number of a fixed precision.
If you just need BigDecimal in C# I would just suggest to find and use an existing implementation. For example https://gist.github.com/nberardi/2667136 (I am not the author, but it seems fine). If you HAVE to implement it for any reason (school, etc) even then I would just resort to using BigInteger. If you have to implement it with byte arrays... You can still benefit from the idea of using scale. You obviously have to take any extra digits after your operations such as "PerformAdd" and then carry them over to the main number. However problems don't stop there. When you begin implementing multiplication you will run into more issues and you will have to start to mix decimal and integer part inevitably. 8.73*0.11 -> 0.9603 0.12*0.026 -> 0.00312 As you can see integer and decimal parts mix up and then decimal part grows into a longer sequence however if you represent these as: 873|2 * 11|2 -> 873*11|4 -> 9603|4 -> 0.9603 12|2 & 26|3 -> 12*26|5 -> 312|5 -> 0.00312 these problems disappear.
How to (theoretically) print all possible double precision numbers in C#?
For a little personal research project I want to generate a string list of all possible values a double precision floating point number can have. I've found the "r" formatting option, which guarantees that the string can be parsed back into the exact same bit representation: string s = myDouble.ToString("r"); But how to generate all possible bit combinations? Preferably ordered by value. Maybe using the unchecked keyword somehow? unchecked { //for all long values myDouble[i] = myLong++; } Disclaimer: It's more a theoretical question, I am not going to read all the numbers... :)
using unsafe code: ulong i = 0; //long is 64 bit, like double unsafe { double* d = (double*)&i; for(;i<ulong.MaxValue;i++) Console.WriteLine(*d); }
You can start with all possible values 0 <= x < 1. You can create those by having zero for exponent and use different values for the mantissa. The mantissa is stored in 52 bits of the 64 bits that make a double precision number, so that makes for 2 ^ 52 = 4503599627370496 different numbers between 0 and 1. From the description of the decimal format you can figure out how the bit pattern (eight bytes) should be for those numbers, then you can use the BitConverter.ToDouble method to do the conversion. Then you can set the first bit to make the negative version of all those numbers. All those numbers are unique, beyond that you will start getting duplicate values because there are several ways to express the same value when the exponent is non-zero. For each new non-zero exponent you would get the value that were not possible to express with the previously used expontents. The values between 0 and 1 will however keep you busy for the forseeable future, so you can just start with those.
This should be doable in safe code: Create a bit string. Convert that to a double. Output. Increment. Repeat.... A LOT. string bstr = "01010101010101010101010101010101"; // this is 32 instead of 64, adjust as needed long v = 0; for (int i = bstr.Length - 1; i >= 0; i--) v = (v << 1) + (bstr[i] - '0'); double d = BitConverter.ToDouble(BitConverter.GetBytes(v), 0); // increment bstr and loop
Finding the number of places after the decimal point of a Double
I have a Double value: double a = 4.5565; What is the easiest way to calculate the number of digits after the decimal point (4 in this case). I know that I can convert to string and do a split and take the length. But is there an easier way?
There's no easy way, especially since the number of digits mathematically speaking might be far more than displayed. For example, 4.5565 is actually stored as 4.556499999999999772626324556767940521240234375 (thanks to harold for calculating that). You're very unlikely to find a useful solution to this problem. EDIT You could come up with some algorithm that works like this: if, as you calculate the decimal representation, you find a certain number of 9s (or zeros) in succession, you round up (or down) to the last place before the series of 9s (or zeros) began. I suspect that you would find more trouble down that road than you would anticipate.
var precision = 0; var x = 1.345678901m; while (x*(decimal)Math.Pow(10,precision) != Math.Round(x*(decimal)Math.Pow(10,precision))) precision++; precision will be equal to the number of significant digits of the decimal value (setting x to 1.23456000 will result in a precision of 5 even though 8 digits were originally specified in the literal). This executes in time proportional to the number of decimal places. It counts the number of fractional digits ONLY; you can count the number of places to the left of the decimal point by taking the integer part of Math.Log10(x). It works best with decimals as they have better value precision so there is less rounding error.
Write a function int CountDigitsAfterDecimal(double value) { bool start = false; int count = 0; foreach (var s in value.ToString()) { if (s == '.') { start = true; } else if (start) { count++; } } return count; }
I think this might be a solution: private static int getDecimalCount(double val) { int i=0; while (Math.Round(val, i) != val) i++; return i; } double val9 = 4.5565d; int count9 = getDecimalCount(val9);//result: 4 Sorry for the duplication -> https://stackoverflow.com/a/35238462/1266873
base on james answer bat much clearer: int num = dValue.ToString().Length - (((int)dValue).ToString().Length + 1); num is the exact number of digits after the decimal point. without including 0 like this(25.520000) in this case, you will get num= 2
I Think String solution is best : ((a-(int)a)+"").length-2
I'll perhaps use this code if I needed, myDoubleNumber.ToString("R").Split('.')[1].Length "R" here is Round Trip Format Specifier We need to check for the index bounds first of course.
Another solution would be to use some string functions: private int GetSignificantDecimalPlaces(decimal number, bool trimTrailingZeros = true) { var stemp = Convert.ToString(number); if (stemp.IndexOf(Application.CurrentCulture.NumberFormat.NumberDecimalSeparator) < 0) return 0; if (trimTrailingZeros) stemp = stemp.TrimEnd('0'); return stemp.Length - 1 - stemp.IndexOf(Application.CurrentCulture.NumberFormat.NumberDecimalSeparator); } Remember to use System.Windows.Forms to get access to Application.CurrentCulture
How can I perform division in a program, digit by digit?
I'm messing around with writing a class similar to mpz (C) or BigInteger (Java). This is just for fun, so please don't go on about how I shouldn't be writing my own. I have a class similar to: public class HugeInt { public List<Integer> digits; public HugeInt(String value) { // convert string value into its seperate digits. // store them in instance variable above } } Now, doing the add() and subtract() method of this class are pretty simple. Here is an example: private List<Integer> add(List<Integer> a, List<Integer> b) { List<Integer> smallerDigits = (compareDigits(a,b) < 0) ? a : b; List<Integer> largerDigits = (compareDigits(a,b) >= 0) ? a : b; List<Integer> result = new ArrayList<Integer>(); int carry = 0; for(int i = 0; i < largerDigits.size(); i++) { int num1 = largerDigits.get(i); int num2 = (i < smallerDigits.size()) ? smallerDigits.get(i) : 0; result.add((num1 + num2 + carry) % 10); carry = ((num1 + num2 + carry) / 10); } if (carry != 0) result.add(carry); return result; } Similarly, doing the multiply wasn't that hard either. I see on wikipedia there is a page on Division Algorithms, but I'm not sure which one is appropriate for what I'm trying to do. Because these positive integers (represented as digits) can be arbitrarily long, I want to make sure I don't attempt to do any operations on anything other than digit-by-digit basis. However, can anyone point me in the right direction for doing a division of two numbers that are represented as List<Integer>'s? Also, I can ignore the remainder as this is integer division.
You could just do long division, but this certainly isn't the optimal way to do it (edit: although it seems that something like this is a good way to do it). You could look at other implementations of big integer libraries, and a bit of Googling turns up a fair bit of useful information.
This may be a slight overkill, but if this is the kind of things you do for fun, you'll enjoy reading this: http://www.fizyka.umk.pl/nrbook/c20-6.pdf (that's "Arithmetic at Arbitrary Precision" from "Numerical recipes in C"). Pretty fascinating, as is most of this book, with good explanations and lots of code.
Since I assume you're just dealing with integer division it's not very hard. Multiplication is repeated addition, division is the opposite - repeated subtraction. So what you'll do is check how many times you can subtract the divisor from the dividend. For example, 3 can be subtracted from 10 3 times without going <0, so the integer division quotient is 3.
This article A Larger Integer does not show how to implement digit by digit operations for "larger integers", but it does show how to implement a (apparently fully functional) 128 bit integer in terms of two Int64 types. I would imagine that it would not be too hard to extend the approach to use an array of Int64 types to yield an arbitary length integer. I just spent a few minutes looking back over the article and the implementation of multiply looks like it could get pretty involved for arbitrary length. The article shows how to implement division (quotient and remainder) using binary division.