I'm trying to make a function HundredPosToZero to convert hundred position to zero, for example :
HundredPosToZero(4239) // 4039
This is my implement :
public HundredPosToZero(int num){
return num / 1000 * 1000 + num % 100;
}
However, I'm thinking of why not use bitwise operator like 4239 & 1011 to do the same thing? But I can not figure out how to implement it since 4239 is not a binary, any advice with this approach?
Not really. There is nothing special about decimal hundreds in binary. It would be possible with e.g. a hexadecimal number, but decimal numbers don't play well with binary :)
It is simply impossible if you want this operation to be the same for all numbers as "hundreds" in regular representation of integers don't occupy the same set of bits.
If you use some other binary representation of numbers (like BCD) that allocates groups of bits to unique decimal digits then you can do that easily.
Related
I know you can convert the Int to a string and get the digit at position x using the indexer as if it was a char array, but this conversion becomes a bit of an overhead when you're dealing with multiple large numbers.
Is there a way to retrieve a digit at position x without converting the number to a string?
EDIT:
Thank you all, I will benchmark the proposed methods and check if it is any better than converting to a string. Thread will stay unanswered for 24h in case anyone has better ideas.
EDIT 2:
After some simple tests on ulong numbers, I have concluded that converting to strings and extracting the digit can be up to 50% slower compared to the methods provided below, see approved answer.
You could do something like this:
int ith_digit(int n, int i) {
return (int) (n / pow(10, i)) % 10;
}
We can get the ith digit by reducing the number down to a point where that digit we want becomes in the one's place, example:
Let's say you wanted the third digit in 12345, then by reducing it to 123 (by dividing it by 10 i number of times) we can then take the remainder of that number divided by ten to get the last digit, which is the digit we wanted.
I have tried BigInteger, decimal, float and long but no luck.
Screenshot of required output example
It is a fairly easy task to write your own rational class; remember, rationals are just pairs of integers, and you already have BigInteger.
In this series of articles I show how to devise your own big integer and big rational classes starting from absolutely nothing, not even integers. Note that this is not fast and not intended to be fast; it is intended to be educational. You can use the techniques I describe in this series to help you when designing your arithmetic class.
https://ericlippert.com/2013/09/16/math-from-scratch-part-one/
Or, if you don't want to write it yourself, you can always use the one from Microsoft:
http://bcl.codeplex.com/wikipage?title=BigRational&referringTitle=Home
But that said...
I need a minimum of 128 decimal places to calculate precise probabilities of events between different time steps
Do you need 128 decimal places to represent 128 digits of precision, or of magnitude? Because if it is just magnitude, then simply do a transformation of your probability math into logarithms and do the math in doubles.
The easiest way to achieve arbitrary precision numbers is to combine the BigInteger class from System.Numerics with an int exponent. You could use BigInteger for your exponent, but this is likely overkill as the numbers would be well beyong meaningful in scale.
So if you create a class along these lines:
public class ArbDecimal
{
BigInteger value;
int exponent;
public override string ToString()
{
StringBuilder sb = new StringBuilder();
int place;
foreach (char digit in value.ToString())
{
if (place++ == value.ToString().Length - exponent)
{
sb.Append('.');
}
sb.Append(digit);
}
return sb.ToString();
}
}
You should then be able to define your mathematical operations using the laws of indices with the value and exponent fields.
For instance, to achieve addition, you would scale the larger value to have the same exponent as the smaller one by multiplying it by 10^(largerExp-smallerExp) then adding the two values and rescaling.
In your class, the number 0.01 would be represented like:
value = 1
exponent = -2
Due to the fact that 1*10^-2 = 0.01.
Utilising this method, you can store arbitrarily precise (and large) numbers limited only by the available ram and the .NET framework's object size limit.
I am wondering how you take a number (for example 9), convert it to a 32 int (00000000000000000000000000001001), then invert or flip every bit (11111111111111111111111111110110) so that the zeroes become ones and the ones become zeroes.
I know how to do that by replacing the numbers in a string, but I need to know how to do that with binary operators on a binary number.
I think you have to use this operator, "~", but it just gives me a negative number when I use it on a value.
That is doing the correct functionality. The int data type within C# uses signed integers, so 11111111111111111111111111110110 is in fact a negative number.
As Marc pointed out, if you want to use unsigned values declare your number as a uint.
If you look at the decimal version of your number then its a negative number.
If you declare it as a unsigned int then its a positive one.
But this doesnt matter, binary it will always be 11111111111111111111111111110110.
Try this:
int number = 9;
Console.WriteLine(Convert.ToString(number, 2)); //Gives you 1001
number = ~number; //Invert all bits
Console.WriteLine(Convert.ToString(number, 2));
//Gives you your wanted result: 11111111111111111111111111110110
The following test will fail in C#
Assert.AreEqual<double>(10.0d, 16.1d - 6.1d);
The problem appears to be a floating point error.
16.1d - 6.1d == 10.000000000000002
This is causing me headaches in writing unit tests for code that uses double. Is there a way to fix this?
There is no exact conversion between the decimal system and the binary representation of a double (see excellent comment by #PatriciaShanahan below on why).
In this case the .1 part of the numbers is the problem, it cannot be finitely represented in a double (like 1/3 can't be finitely represented exactly as a decimal number).
A code snippet to explain what happends:
double larger = 16.1d; //Assign closest double representation of 16.1.
double smaller = 6.1; //Assign closest double representation of 6.1.
double diff = larger - smaller; //Assign closest diff between larger and
//smaller, but since a smaller value has a
//larger precision the result will have better
//precision than larger but worse than smaller.
//The difference shows up as the ...000002.
Always use the Assert.Equal overload which takes a delta parameter when comparing doubles.
Alternatively if you really need exact decimal conversion, use the decimal data type, that has another binary representation and would return exactly 10 in your example.
Floatingoint numbers are an estimate of the actual value based on an exponent so the test fails correctly. If you require exact equivalence in two decimal numbers you may need to check out the decimal data type.
If you are using NUnit please use the Within option. Here can you find additional information: http://www.nunit.org/index.php?p=equalConstraint&r=2.6.2.
I agree with anders abel. There won't be a way to do this using a float number representation. In direct result of IEE 1985-754 only the numbers that can be represented by
can be stored and calculated with precisly (as long as the chosen bit number allows this).
For Example : 1024 * 1.75 * 183.375 / 1040.0675 <-- will be stored precisly
10 / 1.1 <-- wont be stored precisly
If you are hardly interested in exact representation of rational numbers you could write your own number-implementation using fractions.
This could be done by saving numerator, denominator and sign. Then operations like multiply, subtract, etc. need to be implemented (very hard to ensure good performance). A toString()-method could look like this (I assume cachedRepresentation, cachedDotIndex and cachedNumerator to be member-variables)
public String getString(int digits) {
if(this.cachedRepresentation == ""){
this.cachedRepresentation += this.positiveSign ? "" : "-";
this.cachedRepresentation += this.numerator/this.denominator;
this.cachedNumerator = 10 * (this.numerator % this.denominator);
this.cachedDotIndex = this.cachedRepresentation.Length;
this.cachedRepresentation += ".";
}
if ((this.cachedDotIndex + digits) < this.cachedRepresentation.Length)
return this.cachedRepresentation.Substring(0, this.cachedDotIndex + digits + 1);
while((this.cachedDotIndex + digits) >= this.cachedRepresentation.Length){
this.cachedRepresentation += this.cachedNumerator / this.denominator;
this.cachedNumerator = 10 * (this.cachedNumerator % denominator);
}
return cachedRepresentation;
}
This worked for me. At the operations itself with long numbers I got some problems with too small datatypes (usually I don't use c#). I think for an experienced c#-developer it should be no problem to implement this without problems of to small datatypes.
If you want to implement this you should do minifications of the fraction at initializing and before operations using euclids greatest-common-divider.
Non rational numbers can (in every case I know) be specified by a algorithm that comes as close to the exact representation as you want (and computer allows).
There is a similar question in here. Sometimes that solution gives exceptions because the numbers might be to large.
I think that if there is a way of looking at the bytes of a decimal number it will be more efficient. For example a decimal number has to be represented by some n number of bytes. For example an Int32 is represented by 32 bits and all the numbers that start with the bit of 1 are negative. Maybe there is some kind of similar relationship with decimal numbers. How could you look at the bytes of a decimal number? or the bytes of an integer number?
If you are really talking about decimal numbers (as opposed to floating-point numbers), then Decimal.GetBits will let you look at the individual bits of a decimal. The MSDN page also contains a description of the meaning of the bits.
On the other hand, if you just want to check whether a number has a fractional part or not, doing a simple
var hasFractionalPart = (myValue - Math.Round(myValue) != 0)
is much easier than decoding the binary structure. This should work for decimals as well as classic floating-point data types such as float or double. In the latter case, due to floating-point rounding error, it might make sense to check for Math.Abs(myValue - Math.Round(myValue)) < someThreshold instead of comparing to 0.
If you want a reasonably efficient way of getting the 'decimal' value of a decimal type you can just mod it by one.
decimal number = 4.75M;
decimal fractionalPart = number % 1;
Console.WriteLine(fractionalPart); //will print 0.75
While it may not be the theoretically optimal solution, it'll be quite fast, and almost certainly fast enough for your purposes (far better than string manipulation and parsing, which is a common naive approach).
You can use Decimal.GetBits in order to retrieve the bits from a decimal structure.
The MSDN page linked above details how they are laid out in memory:
The binary representation of a Decimal number consists of a 1-bit sign, a 96-bit integer number, and a scaling factor used to divide the integer number and specify what portion of it is a decimal fraction. The scaling factor is implicitly the number 10, raised to an exponent ranging from 0 to 28.
The return value is a four-element array of 32-bit signed integers.
The first, second, and third elements of the returned array contain the low, middle, and high 32 bits of the 96-bit integer number.
The fourth element of the returned array contains the scale factor and sign. It consists of the following parts:
Bits 0 to 15, the lower word, are unused and must be zero.
Bits 16 to 23 must contain an exponent between 0 and 28, which indicates the power of 10 to divide the integer number.
Bits 24 to 30 are unused and must be zero.
Bit 31 contains the sign; 0 meaning positive, and 1 meaning negative.
Going with Oded's detailed info to use GetBits, I came up with this
const int EXP_MASK = 0x00FF0000;
bool hasDecimal = (Decimal.GetBits(value)[3] & EXP_MASK) != 0x0;