In this code, I have a requirement like below:
decimal col;
if (condition)
{
(decimal)col = (decimal)col | ((decimal)System.Math.Pow(2, 0));
}
When this code is compiled, I get an error saying
Operator | cannot be applied to operands of type 'decimal' and 'decimal'
Can anyone explain, please? Thanks
Big numbers
As the compile-time-error says, you cannot use | on decimal. The decimal type is for numbers like 12.34. If you're only using numbers like 12 or 34 then you may be better off using int (between ±2 billion) or long (between ±9 quintillion) depending how big your integer is.
Any number raised to the power zero, n0 equals 1 so your Math.Pow(2, 0) can be replaced by 1.
Your code could then look like this, which will compile.
int col;
and
if (condition)
col = col | 1;
Finally, you may prefer to use the ternary operator ?: to in-line your if statement, do whichever is more readable in your situation:
col = condition ? (col | 1) : col;
Really big numbers
Using .Net 4.0 or above
If you need to use REALLY BIG integers, there is a class for that! System.Numerics.BigInteger (in System.Numerics.dll).
The BigInteger type is an immutable type that represents an arbitrarily large integer whose value in theory has no upper or lower bounds.
Your declaration would then become:
BigInteger col;
And your bitwise operations as normal.
Using .Net 2.0 or above
Check out the project IntX
IntX is an arbitrary precision integers library written in pure C# 2.0 with fast - about O(N * log N) - multiplication/division algorithms implementation. It provides all the basic arithmetic operations on integers, comparing, bitwise shifting etc.
Reference: Big integers in C#
Cast it to Int64 then apply | operator.
decimal d1 = ..;
decimal d2 = ..;
var res = (long)d1 | (long)d2;
Related
Before you read, please be aware that I'm aware of the differences between integer and floating-point division, and I'm aware of how BigInteger.DivRem and BigInteger.Divide.
Consider the following code examples:
BigInteger a = new(5);
BigInteger b = new(2);
BigInteger div = BigInteger.DivRem(a, b, out BigInteger rem);
Console.WriteLine($"{div}.{rem}");
Output = 2.1
BigInteger a = new(5678);
BigInteger b = new(1234);
BigInteger div = BigInteger.DivRem(a, b, out BigInteger rem);
Console.WriteLine($"{div}.{rem}");
Output = 4.742
Neither of the outputs is correct (in the context of what I'm asking). Sure, they're correct in the sense that they're displaying a division and a remainder formatted as ${div}.{rem}, but in my case, that's not what I'm looking for.
The correct values would be 2.5 and 4.6012965964 (with a scale of 10 digits) respectively.
Is there a way to convert/represent the remainder as a fractional value, rather than as a remainder?
Note: I know there is float, double and decimal, but those aren't the solution I'm looking for.
This seems to work:
BigInteger a = new(5678);
BigInteger b = new(1234);
BigInteger div = BigInteger.DivRem(a, b, out BigInteger rem);
var decimalDigits = new List<BigInteger>();
while (rem != 0 && decimalDigits.Count < 10)
{
rem *= 10;
decimalDigits.Add(BigInteger.DivRem(rem, b, out rem));
}
Console.WriteLine($"{div}.{string.Concat(decimalDigits)}");
This is pretty much just an implementation of long division.
You have misunderstood - what you are doing is integer arithmetic on big integers and the results are correct. Read here Math.DivRem() (to understand DIV and REM as concepts, forget about integral type for now).
What you seem to be after is a floating point type with precision greater than double. Last time I looked no such type exists in .Net, except for a few privateer efforts like QPFloat
Does anyone know why integer division in C# returns an integer and not a float?
What is the idea behind it? (Is it only a legacy of C/C++?)
In C#:
float x = 13 / 4;
//== operator is overridden here to use epsilon compare
if (x == 3.0)
print 'Hello world';
Result of this code would be:
'Hello world'
Strictly speaking, there is no such thing as integer division (division by definition is an operation which produces a rational number, integers are a very small subset of which.)
While it is common for new programmer to make this mistake of performing integer division when they actually meant to use floating point division, in actual practice integer division is a very common operation. If you are assuming that people rarely use it, and that every time you do division you'll always need to remember to cast to floating points, you are mistaken.
First off, integer division is quite a bit faster, so if you only need a whole number result, one would want to use the more efficient algorithm.
Secondly, there are a number of algorithms that use integer division, and if the result of division was always a floating point number you would be forced to round the result every time. One example off of the top of my head is changing the base of a number. Calculating each digit involves the integer division of a number along with the remainder, rather than the floating point division of the number.
Because of these (and other related) reasons, integer division results in an integer. If you want to get the floating point division of two integers you'll just need to remember to cast one to a double/float/decimal.
See C# specification. There are three types of division operators
Integer division
Floating-point division
Decimal division
In your case we have Integer division, with following rules applied:
The division rounds the result towards zero, and the absolute value of
the result is the largest possible integer that is less than the
absolute value of the quotient of the two operands. The result is zero
or positive when the two operands have the same sign and zero or
negative when the two operands have opposite signs.
I think the reason why C# use this type of division for integers (some languages return floating result) is hardware - integers division is faster and simpler.
Each data type is capable of overloading each operator. If both the numerator and the denominator are integers, the integer type will perform the division operation and it will return an integer type. If you want floating point division, you must cast one or more of the number to floating point types before dividing them. For instance:
int x = 13;
int y = 4;
float x = (float)y / (float)z;
or, if you are using literals:
float x = 13f / 4f;
Keep in mind, floating points are not precise. If you care about precision, use something like the decimal type, instead.
Since you don't use any suffix, the literals 13 and 4 are interpreted as integer:
Manual:
If the literal has no suffix, it has the first of these types in which its value can be represented: int, uint, long, ulong.
Thus, since you declare 13 as integer, integer division will be performed:
Manual:
For an operation of the form x / y, binary operator overload resolution is applied to select a specific operator implementation. The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.
The predefined division operators are listed below. The operators all compute the quotient of x and y.
Integer division:
int operator /(int x, int y);
uint operator /(uint x, uint y);
long operator /(long x, long y);
ulong operator /(ulong x, ulong y);
And so rounding down occurs:
The division rounds the result towards zero, and the absolute value of the result is the largest possible integer that is less than the absolute value of the quotient of the two operands. The result is zero or positive when the two operands have the same sign and zero or negative when the two operands have opposite signs.
If you do the following:
int x = 13f / 4f;
You'll receive a compiler error, since a floating-point division (the / operator of 13f) results in a float, which cannot be cast to int implicitly.
If you want the division to be a floating-point division, you'll have to make the result a float:
float x = 13 / 4;
Notice that you'll still divide integers, which will implicitly be cast to float: the result will be 3.0. To explicitly declare the operands as float, using the f suffix (13f, 4f).
Might be useful:
double a = 5.0/2.0;
Console.WriteLine (a); // 2.5
double b = 5/2;
Console.WriteLine (b); // 2
int c = 5/2;
Console.WriteLine (c); // 2
double d = 5f/2f;
Console.WriteLine (d); // 2.5
It's just a basic operation.
Remember when you learned to divide. In the beginning we solved 9/6 = 1 with remainder 3.
9 / 6 == 1 //true
9 % 6 == 3 // true
The /-operator in combination with the %-operator are used to retrieve those values.
The result will always be of type that has the greater range of the numerator and the denominator. The exceptions are byte and short, which produce int (Int32).
var a = (byte)5 / (byte)2; // 2 (Int32)
var b = (short)5 / (byte)2; // 2 (Int32)
var c = 5 / 2; // 2 (Int32)
var d = 5 / 2U; // 2 (UInt32)
var e = 5L / 2U; // 2 (Int64)
var f = 5L / 2UL; // 2 (UInt64)
var g = 5F / 2UL; // 2.5 (Single/float)
var h = 5F / 2D; // 2.5 (Double)
var i = 5.0 / 2F; // 2.5 (Double)
var j = 5M / 2; // 2.5 (Decimal)
var k = 5M / 2F; // Not allowed
There is no implicit conversion between floating-point types and the decimal type, so division between them is not allowed. You have to explicitly cast and decide which one you want (Decimal has more precision and a smaller range compared to floating-point types).
As a little trick to know what you are obtaining you can use var, so the compiler will tell you the type to expect:
int a = 1;
int b = 2;
var result = a/b;
your compiler will tell you that result would be of type int here.
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.
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.
I've a double variable called x.
In the code, x gets assigned a value of 0.1 and I check it in an 'if' statement comparing x and 0.1
if (x==0.1)
{
----
}
Unfortunately it does not enter the if statement
Should I use Double or double?
What's the reason behind this? Can you suggest a solution for this?
It's a standard problem due to how the computer stores floating point values. Search here for "floating point problem" and you'll find tons of information.
In short – a float/double can't store 0.1 precisely. It will always be a little off.
You can try using the decimal type which stores numbers in decimal notation. Thus 0.1 will be representable precisely.
You wanted to know the reason:
Float/double are stored as binary fractions, not decimal fractions. To illustrate:
12.34 in decimal notation (what we use) means
1 * 101 + 2 * 100 + 3 * 10-1 + 4 * 10-2
The computer stores floating point numbers in the same way, except it uses base 2: 10.01 means
1 * 21 + 0 * 20 + 0 * 2-1 + 1 * 2-2
Now, you probably know that there are some numbers that cannot be represented fully with our decimal notation. For example, 1/3 in decimal notation is 0.3333333…. The same thing happens in binary notation, except that the numbers that cannot be represented precisely are different. Among them is the number 1/10. In binary notation that is 0.000110011001100….
Since the binary notation cannot store it precisely, it is stored in a rounded-off way. Hence your problem.
double and Double are the same (double is an alias for Double) and can be used interchangeably.
The problem with comparing a double with another value is that doubles are approximate values, not exact values. So when you set x to 0.1 it may in reality be stored as 0.100000001 or something like that.
Instead of checking for equality, you should check that the difference is less than a defined minimum difference (tolerance). Something like:
if (Math.Abs(x - 0.1) < 0.0000001)
{
...
}
You need a combination of Math.Abs on X-Y and a value to compare with.
You can use following Extension method approach
public static class DoubleExtensions
{
const double _3 = 0.001;
const double _4 = 0.0001;
const double _5 = 0.00001;
const double _6 = 0.000001;
const double _7 = 0.0000001;
public static bool Equals3DigitPrecision(this double left, double right)
{
return Math.Abs(left - right) < _3;
}
public static bool Equals4DigitPrecision(this double left, double right)
{
return Math.Abs(left - right) < _4;
}
...
Since you rarely call methods on double except ToString I believe its pretty safe extension.
Then you can compare x and y like
if(x.Equals4DigitPrecision(y))
Comparing floating point number can't always be done precisely because of rounding. To compare
(x == .1)
the computer really compares
(x - .1) vs 0
Result of sybtraction can not always be represeted precisely because of how floating point number are represented on the machine. Therefore you get some nonzero value and the condition evaluates to false.
To overcome this compare
Math.Abs(x- .1) vs some very small threshold ( like 1E-9)
From the documentation:
Precision in Comparisons
The Equals method should be used with caution, because two apparently equivalent values can be unequal due to the differing precision of the two values. The following example reports that the Double value .3333 and the Double returned by dividing 1 by 3 are unequal.
...
Rather than comparing for equality, one recommended technique involves defining an acceptable margin of difference between two values (such as .01% of one of the values). If the absolute value of the difference between the two values is less than or equal to that margin, the difference is likely to be due to differences in precision and, therefore, the values are likely to be equal. The following example uses this technique to compare .33333 and 1/3, the two Double values that the previous code example found to be unequal.
So if you really need a double, you should use the techique described on the documentation.
If you can, change it to a decimal. It' will be slower, but you won't have this type of problem.
Use decimal. It doesn't have this "problem".
Exact comparison of floating point values is know to not always work due to the rounding and internal representation issue.
Try imprecise comparison:
if (x >= 0.099 && x <= 0.101)
{
}
The other alternative is to use the decimal data type.
double (lowercase) is just an alias for System.Double, so they are identical.
For the reason, see Binary floating point and .NET.
In short: a double is not an exact type and a minute difference between "x" and "0.1" will throw it off.
Double (called float in some languages) is fraut with problems due to rounding issues, it's good only if you need approximate values.
The Decimal data type does what you want.
For reference decimal and Decimal are the same in .NET C#, as are the double and Double types, they both refer to the same type (decimal and double are very different though, as you've seen).
Beware that the Decimal data type has some costs associated with it, so use it with caution if you're looking at loops etc.
Official MS help, especially interested "Precision in Comparisons" part in context of the question.
https://learn.microsoft.com/en-us/dotnet/api/system.double.equals
// Initialize two doubles with apparently identical values
double double1 = .333333;
double double2 = (double) 1/3;
// Define the tolerance for variation in their values
double difference = Math.Abs(double1 * .00001);
// Compare the values
// The output to the console indicates that the two values are equal
if (Math.Abs(double1 - double2) <= difference)
Console.WriteLine("double1 and double2 are equal.");
else
Console.WriteLine("double1 and double2 are unequal.");
1) Should i use Double or double???
Double and double is the same thing. double is just a C# keyword working as alias for the class System.Double
The most common thing is to use the aliases! The same for string (System.String), int(System.Int32)
Also see Built-In Types Table (C# Reference)
Taking a tip from the Java code base, try using .CompareTo and test for the zero comparison. This assumes the .CompareTo function takes in to account floating point equality in an accurate manner. For instance,
System.Math.PI.CompareTo(System.Math.PI) == 0
This predicate should return true.
// number of digits to be compared
public int n = 12
// n+1 because b/a tends to 1 with n leading digits
public double MyEpsilon { get; } = Math.Pow(10, -(n+1));
public bool IsEqual(double a, double b)
{
// Avoiding division by zero
if (Math.Abs(a)<= double.Epsilon || Math.Abs(b) <= double.Epsilon)
return Math.Abs(a - b) <= double.Epsilon;
// Comparison
return Math.Abs(1.0 - a / b) <= MyEpsilon;
}
Explanation
The main comparison function done using division a/b which should go toward 1. But why division? it simply puts one number as reference defines the second one. For example
a = 0.00000012345
b = 0.00000012346
a/b = 0.999919002
b/a = 1.000081004
(a/b)-1 = 8.099789405475458e-5
1-(b/a) = 8.100445524503848e-5
or
a=12345*10^8
b=12346*10^8
a/b = 0.999919002
b/a = 1.000081004
(a/b)-1 = 8.099789405475458e-5
1-(b/a) = 8.100445524503848e-5
by division we get rid of trailing or leading zeros (or relatively small numbers) that pollute our judgement of number precision. In the example, the comparison is of order 10^-5, and we have 4 number accuracy, because of that in the beginning code I wrote comparison with 10^(n+1) where n is number accuracy.
Adding onto Valentin Kuzub's answer above:
we could use a single method that supports providing nth precision number:
public static bool EqualsNthDigitPrecision(this double value, double compareTo, int precisionPoint) =>
Math.Abs(value - compareTo) < Math.Pow(10, -Math.Abs(precisionPoint));
Note: This method is built for simplicity without added bulk and not with performance in mind.
As a general rule:
Double representation is good enough in most cases but can miserably fail in some situations. Use decimal values if you need complete precision (as in financial applications).
Most problems with doubles doesn't come from direct comparison, it use to be a result of the accumulation of several math operations which exponentially disturb the value due to rounding and fractional errors (especially with multiplications and divisions).
Check your logic, if the code is:
x = 0.1
if (x == 0.1)
it should not fail, it's to simple to fail, if X value is calculated by more complex means or operations it's quite possible the ToString method used by the debugger is using an smart rounding, maybe you can do the same (if that's too risky go back to using decimal):
if (x.ToString() == "0.1")
Floating point number representations are notoriously inaccurate because of the way floats are stored internally. E.g. x may actually be 0.0999999999 or 0.100000001 and your condition will fail. If you want to determine if floats are equal you need to specify whether they're equal to within a certain tolerance.
I.e.:
if(Math.Abs(x - 0.1) < tol) {
// Do something
}
My extensions method for double comparison:
public static bool IsEqual(this double value1, double value2, int precision = 2)
{
var dif = Math.Abs(Math.Round(value1, precision) - Math.Round(value2, precision));
while (precision > 0)
{
dif *= 10;
precision--;
}
return dif < 1;
}
To compare floating point, double or float types, use the specific method of CSharp:
if (double1.CompareTo(double2) > 0)
{
// double1 is greater than double2
}
if (double1.CompareTo(double2) < 0)
{
// double1 is less than double2
}
if (double1.CompareTo(double2) == 0)
{
// double1 equals double2
}
https://learn.microsoft.com/en-us/dotnet/api/system.double.compareto?view=netcore-3.1