How to carry number from decimal to whole byte array - c#
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.
Related
What is the conventional way to convert a range of bits to an integer value in c# .net?
I've been programming for many years, but have never needed to use bitwise operations too much or really deal with data too much on a bit or even byte level, until now. So, please forgive my lack of knowledge. I'm having to process streaming message frame data that I'm getting via socket communication. The message frames are a series of hex bytes encoded Big Endian which I read into a byte array called byteArray. Take the following 2 bytes for example: 0x03 0x20 The data I need is represented in the first 14 bits - meaning I need to convert the first 14 bits into an int value. (The last 2 bits represent 2 other bool values). I have coded the following to accomplish this: if (BitConverter.IsLittleEndian) { Array.Reverse(byteArray); } BitArray bitArray = GetBitArrayFromRange(new BitArray(byteArray), 0, 14); int dataValue = GetIntFromBitArray(bitArray) The dataValue variable ends up with the correct result which is: 800 The two functions I'm calling are here: private static BitArray GetBitArrayFromRange(BitArray bitArray, int startIndex, int length) { var newBitArray = new BitArray(length); for (int i = startIndex; i < length; i++) { newBitArray[i] = bitArray.Get(i); } return newBitArray; } private static int GetIntFromBitArray(BitArray bitArray) { int[] array = new int[1]; bitArray.CopyTo(array, 0); return array[0]; } Since I have a lack of experience in this area, my question is: Does this code look correct/reasonable? Or, is there a more preferred/conventional way of accomplishing what I need? Thanks!
"The dataValue variable ends up with the correct result which is: 800" Shouldn't that correct result be actually 200? 1) 00000011 00100001 : is integer 0x0321 (so now skip beginning two bits 01...) 2) xx000000 11001000 : is extracted last 14 bits (missing 2 bits, so those xx count as zero) 3) 00000000 11001000 : is expected final result from 14-bits extraction = 200 At present it looks like you have an empty (zero filled) 16 bits into which you put the 14 bits. Somehow you putting in exact same position (left-hand side instead of right-hand side) Original bits : 00000011 00100001 Slots 16 bit : XXXXXXXX XXXXXXXX Instead of this : XX000000 11001000 //correct way You have done : 00000011 001000XX //wrong way Your right-hand side XX are zero so your result is 00000011 00100000 which would give 800, but that's wrong because it's not the true value of those specific 14 bits you extracted. "Is there a more preferred/conventional way of accomplishing what I need?" I guess bit-shifting is the conventional way... Solution (pseudo-code) : var myShort = 0x0321; //Short means 2 bytes var answer = (myShort >> 2); //bitshift to right-hand side by 2 places By nudging everything 2 places/slots towards right, you can see how the two now-empty places at far-left becomes the XX (automatically zero until you change them), and by nudging you have also just removed the (right-side) 2 bits you wanted to ignore... Leaving you with correct 14-bit value. PS: Regarding your code... I've not had chance to test it all but the below logic seems more appropriate for your GetBitArrayFromRange function : for (int i = 0; i < (length-1); i++) { newBitArray[i] = bitArray.Get(startIndex + i); }
How to make subtraction in numeric strings while holding the string length fixed in C#?
8654 -> 8653; 1000 -> 0999; 0100 -> 0099; 0024 -> 0023; 0010 -> 0009; 0007 -> 0006 etc. I have a string variable of fixed length 4; its characters are always numbers. I want to make subtraction while obeying the given rule that its length of 4 must be protected. What I tried: Convert.ToInt32, .Length operations etc. In my code, I always faced some sort of errors. I devised that I can do this via 3 steps: 1. Convert the string value to an (int) integer 2. Subtract "1" in that integer to find a new integer 3. Add "4 - length of new integer" times "0" to the beginning. Anyway, independent of the plotted solution above (since I am a newbee; perhaps even my thought may divert a standard user from a normal plausible approach for solution), is not there a way to perform the above via a function or something else in C#?
A number doesn't have a format, it's string representation has a format. The steps you outlined for performing the arithmetic and outputting the result are correct. I would suggest using PadLeft to output the result in the desired format: int myInt = int.Parse("0100"); myInt = myInt - 1; string output = myInt.ToString().PadLeft(4, '0'); //Will output 0099
Your steps are almost right, however there is a easier way to accomplish getting the leading 0's, use Numeric string formatting. Using the formatting string "D4" it will behave exactly like you want. var oldString = "1000"; var oldNum = Convert.ToInt32(oldString); var newNum = oldNum - 1; var newString = newNum.ToString("D4"); Console.WriteLine(newString); //prints "0999" Click to run example You could also use the custom formatting string "0000".
Well, I think others have implemented what you have implemented already. The reason might be that you didn't post your code. But none of the answers addresses your main question... Your approach is totally fine. To make it reusable, you need to put it into a method. A method can look like this: private string SubtractOnePreserveLength(string originalNumber) { // 1. Convert the string value to an (int) integer // 2. Subtract "1" in that integer to find a new integer // 3. Add "4 - length of new integer" times "0" to the beginning. return <result of step 3 >; } You can then use the method like this: string result = SubtractOnePreserveLength("0100"); // result is 0099
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
1000 digit number in 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 };
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.