Arbitrarily large integers in C# - c#

How can I implement this python code in c#?
Python code:
print(str(int(str("e60f553e42aa44aebf1d6723b0be7541"), 16)))
Result:
305802052421002911840647389720929531201
But in c# I have problems with big digits.
Can you help me?
I've got different results in python and c#. Where can be mistake?

Primitive types (such as Int32, Int64) have a finite length that it's not enough for such big number. For example:
Data type Maximum positive value
Int32 2,147,483,647
UInt32 4,294,967,295
Int64 9,223,372,036,854,775,808
UInt64 18,446,744,073,709,551,615
Your number 305,802,052,421,002,911,840,647,389,720,929,531,201
In this case to represent that number you would need 128 bits. With .NET Framework 4.0 there is a new data type for arbitrarily sized integer numbers System.Numerics.BigInteger. You do not need to specify any size because it'll be inferred by the number itself (it means that you may even get an OutOfMemoryException when you perform, for example, a multiplication of two very big numbers).
To come back to your question, first parse your hexadecimal number:
string bigNumberAsText = "e60f553e42aa44aebf1d6723b0be7541";
BigInteger bigNumber = BigInteger.Parse(bigNumberAsText,
NumberStyles.AllowHexSpecifier);
Then simply print it to console:
Console.WriteLine(bigNumber.ToString());
You may be interested to calculate how many bits you need to represent an arbitrary number, use this function (if I remember well original implementation comes from C Numerical Recipes):
public static uint GetNeededBitsToRepresentInteger(BigInteger value)
{
uint neededBits = 0;
while (value != 0)
{
value >>= 1;
++neededBits;
}
return neededBits;
}
Then to calculate the required size of a number wrote as string:
public static uint GetNeededBitsToRepresentInteger(string value,
NumberStyles numberStyle = NumberStyles.None)
{
return GetNeededBitsToRepresentInteger(
BigInteger.Parse(value, numberStyle));
}

If you just want to be able to use larger numbers there is BigInteger which has a lot of digits.

To find the number of bits you need to store a BigInteger N, you can use:
BigInteger N = ...;
int nBits = Mathf.CeilToInt((float)BigInteger.Log(N, 2.0));

Related

BigInteger.Pow(BigInteger, BigInteger)?

I'm trying to calculate a large number, which requires BigInteger.Pow(), but I need the exponent to also be a BigInteger and not int.
i.e.
BigInteger.Pow(BigInteger)
How can I achieve this?
EDIT: I came up with an answer. User dog helped me to achieve this.
public BigInteger Pow(BigInteger value, BigInteger exponent)
{
BigInteger originalValue = value;
while (exponent-- > 1)
value = BigInteger.Multiply(value, originalValue);
return value;
}
Just from the aspect of general maths, this doesn't make sense. That's why it's not implemented.
Think of this example: Your BigInteger number is 2 and you need to potentiate it by 1024. This means that the result is a 1 KB number (2^1024). Now imagine you take int.MaxValue: Then, your number will consume 2 GB of memory already. Using a BigInteger as an exponent would yield a number beyond memory capacity!
If your application requires numbers in this scale, where the number itself is too large for your memory, you probably want a solution that stores the number and the exponent separately, but that's something I can only speculate about since it's not part of your question.
If your your issue is that your exponent variable is a BigInteger, you can just cast it to int:
BigInteger.Pow(bigInteger, (int)exponent); // exponent is BigInteger
Pow(2, int64.MaxValue) requires 1,152,921 terabytes just to hold the number, for a sense of scale. But here's the function anyways, in case you have a really nice computer.
static BigInteger Pow(BigInteger a, BigInteger b) {
BigInteger total = 1;
while (b > int.MaxValue) {
b -= int.MaxValue ;
total = total * BigInteger.Pow(a, int.MaxValue);
}
total = total * BigInteger.Pow(a, (int)b);
return total;
}
As others have pointed out, raising something to a power higher than the capacity of int is bad news. However, assuming you're aware of this and are just being given your exponent in the form of a BigInteger, you can just cast to an int and proceed on your merry way:
BigInteger.Pow(myBigInt, (int)myExponent);
or, even better,
try
{
BigInteger.Pow(myBigInt, (int)myExponent);
}
catch (OverflowException)
{
// Do error handling and stuff.
}
For me the solution was to use the function BigInteger.ModPow(BigInteger value, BigInteger exponent, BigInteger modulus) because I needed to do a mod afterwards anyway.
The function calculates a given BigInteger to the power of another BigInteger and calculates the modulo with a third BitInteger.
Although it will still take a good amount of CPU Power it can be evaluated because the function already knows about the modulo and therefore can save a ton of memory.
Hope this might help some with the same question.
Edit:
Is available since .Net Framework 4.0 and is in .Net Standard 1.1 and upwards.
I came up with:
public BigInteger Pow(BigInteger value, BigInteger exponent)
{
BigInteger originalValue = value;
while (exponent-- > 1)
value = BigInteger.Multiply(value, originalValue);
return value;
}

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

Convert 24 bit value to float and back

It is possible to convert 24 bit integer value into float and then back to 24 bit integer without losing data?
For example, let's consider 8 bit int, a byte, range is [-127..127] (we drop -128).
public static float ToFloatSample (byte x) { return x / 127f; }
So, if x == -127, result will be -1, if x == 127, result will be 1. If x == 64, result will be ~0.5
public static int ToIntSample (float x) { return (int) (x * 127f); }
So now:
int x = some_number;
float f = ToFloatSample (x);
int y = ToIntSample (f);
Will always x == y ? Using 8 bit int yes, but what if I use 24 bit?
Having thought about your question, I now understand what you're asking.
I understand you have 24-bits which represent a real number n such that -1 <= n <= +1 and you want to load this into an instance of System.Single, and back again.
In C/C++ this is actually quite easy with the frexp and ldexp functions, documented here ( how can I extract the mantissa of a double ), but in .NET it's a more involved process.
The C# language specification (and thusly, .NET) states it uses IEEE-754 1989 format, which means you'll need to dump the bits into an integer type so you can perform the bitwise logic to extract the components. This question has already been asked here on SO except for System.Double instead of System.Single, but converting the answer to work with Single is a trivial exercise for the reader ( extracting mantissa and exponent from double in c# ).
In your case, you'd want to store your 24-bit mantissa value in the low-24 bits of an Int32 and then use the code in that linked question to load and extract it from a Single instance.
Every integer in the range [-16777216, 16777216] is exactly representable as an IEEE 754 32-bit binary floating point number. That includes both the unsigned and 2's complement 24 bit integer ranges. Simple casting will do the job.
The range is wider than you would expect because there is an extra significand bit that is not stored - it is a binary digit that is known not to be zero.

BitArray change bit within range

How can I ensure that when changing a bit from a BitArray, the BitArray value remains in a range.
Example:
Given the range [-5.12, 5.12] and
a = 0100000000000000011000100100110111010010111100011010100111111100 ( = 2.048)
By changing a bit at a random position, I need to ensure that the new value remains in the given range.
I'm not 100% sure what you are doing and this answer assumes you are storing a as a 64-bit value (long) currently. The following code may help point you in the right direction.
const double minValue = -5.12;
const double maxValue = 5.12;
var initialValue = Convert.ToInt64("100000000000000011000100100110111010010111100011010100111111100", 2);
var changedValue = ChangeRandomBit(initialValue); // However you're doing this
var changedValueAsDouble = BitConverter.Int64BitsToDouble(initialValue);
if ((changedValueAsDouble < minValue) || (changedValueAsDouble > maxValue))
{
// Do something
}
It looks like double (64 bits and result has decimal point).
As you may know it has sign bit, exponent and fraction, so you can not change random bit and still have value in the range, with some exceptions:
sign bit can be changed without problem if your range is [-x;+x] (same x);
changing exponent or fraction will require to check new value range but:
changing exponent of fraction bit from 1 to 0 will make |a| less.
I don't know what you are trying to achieve, care to share? Perhaps you are trying to validate or correct something, then you may have a look at this.
Here's an extension method that undoes the set bit if the new value of the float is outside the given range (this is an example only, it relies on the BitArray holding a float with no checks, which is pretty horrible so just hack a solution out of this, incl changing to double):
static class Extension
{
public static void SetFloat(this BitArray array, int index, bool value, float min, float max)
{
bool old = array.Get(index);
array.Set(index, value);
byte[] bytes = new byte[4];
array.CopyTo(bytes, 0);
float f = BitConverter.ToSingle(bytes, 0);
if (f < min || f > max)
array.Set(index, old);
}
}
Example use:
static void Main(string[] args)
{
float f = 2.1f;
byte[] bytes = System.BitConverter.GetBytes(f);
BitArray array = new BitArray(bytes);
array.Set(20, true, -5.12f, 5.12f);
}
If you can actually limit your precision, then this would be a lot easier. For example given the range:
[-5.12, 5.12]
If I multiply 5.12 by 100, I get
[-512, 512]
And the integer 512 in binary is, of course:
1000000000
So now you know you can set any of the first 9 bits and you'll be < 512 if the 10th bit is 0. If you set the 10th bit, you will have to set all the other bits to 0. With a little extra effort, this can be extended to deal with 2's complement negative values too (although, I might be inclined just to convert them to positive values)
Now if you actually need to accommodate the 3 d.p. of 2.048, then you'll need to multiply all you values by 1000 instead and it will be a little more difficult because 5120 in binary is 1010000000000
You know you can do anything you want with everything except the most significant bit (MSB) if the MSB is 0. In this case, if the MSB is 1, but the next 2 bits are 0, you can do anything you want with the remaining bits.
The logic involved with dealing directly with the number in IEEE-754 floating point format is probably going to be torturous.
Or you could just go with the "mutate the value and then test it" approach, if it's out-of-range, go back and try again. Which might be suitable (in practice), but won't be guaranteed to exit.
A final thought, depending on exactly what you are doing, you might want to also look at Gray Codes. The idea of a Gray Code is to make it such that each value is only 1 bit flip apart. With naturally encoded binary, a flip of the MSB has orders of magnitude more impact on the final value than a flip of the LSB.

Hardware RNG - How to use?

Ok, I've just picked up a hardware RNG and it contains some simple functions as below,
GetRandomBytes(UInt Length,out object Array)
GetRandomDoubles(UInt Length,out object Array)
The functions seem to explain themselves pretty well, how would one use these functions effectivly to generate a number between a certain range?
More info from some docs we have found,
GetRandomByte
Return a single byte containing 8 random bits.
GetRandomWord
Return an unsigned integer containing 32 random bits.
GetRandomDouble
Returns a double-precision floating point value uniformly
distributed between 0 (inclusive) and 1 (exclusive).
GetRandomBytes
GetRandomWords
GetRandomDoubles
Fill in an array with random values. These methods all take
two arguments, an integer specifying the number of values
to return (as an unsigned long integer), and the array to
return the values in (as a COM Variant).
To get a random int within a given range, you can use the GetRandomDouble function that is provided by the hardware, and scale that value to fit the desired range. The maximum value is exclusive, since the underlying double range [0,1) is half-open.
int GetRandomInt(int min, int max) {
double d = randHardware.GetRandomDouble();
return ((max-min)*d)+min;
}
If I had those functions without absolutely any other help or indication the first try I would do is this (just looking at the signature):
uint length = 20;
object array;
GetRandomBytes(length, out array);
Then I will try to debug this and see what the actual type of array is after calling the function. Looking at the name of the function I would assume byte[], so I would cast:
byte[] result = (byte[])array;
As far as a range is concerned those function signatures are far from self-explaining. Maybe the length parameter?
Also note that in C# there's no such thing as UInt. There's System.UInt32 and uint which is a shortcut.
NOTE: This uses inclusive ranges. You might want exclusive max, as is typical. Obviously this should be modified to your needs.
Let's say you get a double that's random
public int getIntInRangeFromDouble(int min, int max, double rand) {
int range = max-min+1;
int offset = (int)(range*rand);
return min + offset - 1;
}
You can apply this by taking your random doubles and doing
int[] getIntsFromRandomDoubles(int min, int max, double[] rands) {
int[] result = new int[rands.length];
for(int i = 0; i < rands.length; i++) result[i] = getIntInRangeFromDouble(min,max,rands[i]);
return result;
}

Categories

Resources