Random Number with NextDouble (C#) - c#

I'm programming a perceptron and really need to get the range from the normal NextDouble (0, 1) to (-0.5, 0.5). Problem is, I'm using an array and I'm not sure whether it is possible. Hopefully that's enough information.
Random rdm = new Random();
double[] weights = {rdm.NextDouble(), rdm.NextDouble(), rdm.NextDouble()};

Simply subtract 0.5 from your random number:
double[] weights = {
rdm.NextDouble() - 0.5,
rdm.NextDouble() - 0.5,
rdm.NextDouble() - 0.5
};

If you need a only one decimal value (my wild guess from what I have seen in Wikipedia) and to include both limits, I wouldn't use a double but just a decimal value and then do the math:
(rdm.Next(11) - 5) / 10M;
That will return any of the 11 different possible values from -0.5 to 0.5.
Or you could go the double way but with a rounding, so you can actually hit the upper limit (0.5):
Math.Round(rdm.NextDouble() - 0.5, 1);
This way is probably a tiny bit slower than my first suggestion.

Related

Create random double, unified over whole range of valid doubles

There is Best way to generate a random float in C# for float, and Generating a Random Decimal in C# for decimal, however, there is no question for double yet which covers "the full range of double".
How to properly generate a random double with a uniform distribution over all valid (i.e., non-NaN/infinite/...) values?
Your scaling wouldn't work, because the scaling factor would be actually bigger than double.MaxValue which doesn't work.
var number = r.NextDouble() * 2d - 1d; // r in [-1, 1]
return number * double.MaxValue;
This code snippet first generates a uniform distributed random number in the range [-1,1].
Than it transforms it into your desired range.
This only works, when both ranges are equal, which is true for your use-case ( double.MaxValue == Math.Abs(double.MinValue))
Note: actually the upper bound of Random.NextDouble() is 0.99999999999999978 according to https://learn.microsoft.com/en-us/dotnet/api/system.random.nextdouble?view=netframework-4.7)
According to your question, how to get a range where 1 is included, you could implement the random.NextDouble() method on your own.
The reference implementation (http://referencesource.microsoft.com/#mscorlib/system/random.cs,bb77e610694e64ca) uses the Random.Next() method and maps it to a double, where the Random.Next() method has a range [0, Int32.MaxValue - 1]. So just use r.Next() * (1.0 / (Int32.MaxValue - 1)) which would return double values in the range [0, 1].
By the way, I don't think, the docs are correct, since the maximum value, Random.NextDouble() can generate is 0.999999999534339, which is (Int32.MaxValue - 1) * (1.0 / Int32.MaxValue) and not 0.99999999999999978.

How can I multiply and divide integers without bigger intermediate types?

Currently, I'm developing some fuzzy logic stuff in C# and want to achieve this in a generic way. For simplicity, I can use float, double and decimal to process an interval [0, 1], but for performance, it would be better to use integers. Some thoughts about symmetry also led to the decision to omit the highest value in unsigned and the lowest value in signed integers. The lowest, non-omitted value maps to 0 and the highest, non-omitted value maps to 1. The omitted value is normalized to the next non-omitted value.
Now, I want to implement some compund calculations in the form of:
byte f(byte p1, byte p2, byte p3, byte p4)
{
return (p1 * p2) / (p3 * p4);
}
where the byte values are interpreted as the [0, 1] interval mentioned above. This means p1 * p2 < p1 and p1 * p2 < p2 as opposed to numbers greater than 1, where this is not valid, e. g. 2 * 3 = 6, but 0.1 * 0.2 = 0.02.
Additionally, a problem is: p1 * p2 and p3 * p4 may exceed the range of the type byte. The result of the whole formula may not exceed this range, but the overflow would still occur in one or both parts. Of course, I can just cast to ushort and in the end back to byte, but for an ulong I wouldn't have this possibility without further effort and I don't want to stick to 32 bits. On the other hand, if I return (p1 / p3) * (p2 / p4), I decrease the type escalation, but might run into a result of 0, where the actual result is non-zero.
So I thought of somehow simultaneously "shrinking" both products step by step until I have the result in the [0, 1] interpretation. I don't need an exact value, a heuristic with an error less than 3 integer values off the correct value would be sufficient, and for an ulong an even higher error would certainly be OK.
So far, I have tried to convert the input to a decimal/float/double in the interval [0, 1] and calculated it. But this is completely counterproductive regarding performance. I read stuff about division algorithms, but I couldn't find the one I saw once in class. It was about calculating quotient and remainder simultaneously, with an accumulator. I tried to reconstruct and extend it for factorized parts of the division with corrections, but this breaks, where inidivisibility occurs and I get a too big error. I also made some notes and calculated some integer examples manually, trying to factor out, cancel out, split sums and such fancy derivation stuff, but nothing led to a satisfying result or steps for an algorithm.
Is there a
performant way
to multiply/divide signed (and unsigned) integers as above
interpreted as interval [0, 1]
without type promotion
?
To answer your question as summarised: No.
You need to state (and rank) your overall goals explicitly (e.g., is symmetry more or less important than performance?). Your chances of getting a helpful answer improve with succinctly stating them in the question.
While I think Phil1970's you can ignore scaling for … division overly optimistic, multiplication is enough of a problem: If you don't generate partial results bigger (twice as big) as your "base type", you are stuck with multiplying parts of your operands and piecing the result together.
For ideas about piecing together "larger" results: AVR's Fractional Multiply.
Regarding …in signed integers. The lowest, non-omitted value maps to 0…, I expect that you will find, e.g., excess -32767/32768-coded fractions even harder to handle than two's complement ones.
If you are not careful, you will lost more time doing conversions that it would have take with regular operations.
That being said, an alternative that might make some sense would be to map value between 0 and 128 included (or 0 and 32768 if you want more precision) so that all value are essentially stored multiplied by 128.
So if you have (0.5 * 0.75) / (0.125 * 0.25) the stored values for each of those numbers would be 64, 96, 16 and 32 respectively. If you do those computation using ushort you would have (64 * 96) / (16 * 32) = 6144 / 512 = 12. This would give a result of 12 / 128 = 0.09375.
By the way, you can ignore scaling for addition, substraction and division. For multiplication, you would do the multiplication as usual and then divide by 128. So for 0.5 * 0.75 you would have 64 * 96 / 128 = 48 which correspond to 48 / 128 = 0.375 as expected.
The code can be optimized for the platform particularly if the platform is more efficient with narrow numbers. And if necessary, rounding could be added to operation.
By the way since the scaling if a power of 2, you can use bit shifting for scaling. You might prefer to use 256 instead of 128 particularly if you don't have one cycle bit shifting but then you need larger width to handle some operations.
But you might be able to do some optimization if the most significant bit is not set for example so that you would only use larger width when necessary.

Divide by 3 and Round up (If need be) C#

I have come to a point in my game where I have to implement a feature which divides a number by 3 and makes it a whole integer. i.e. not 3.5 or 2.6 etc....
It was to be a whole number, like 3, or 5.
Does anyone know how I can do this?
Math.Round(num / 3);
or
Math.Ceiling(num / 3);
or
Math.Truncate(num / 3);
Divide by three and round up can be done with the math functions:
int xyzzy = Math.Ceiling (plugh / 3);
or, if the input is an integer, with no functions at all:
int xyzzy = (plugh + 2) / 3;
This can also be done in a more generic way, "divide by n, rounding up":
int xyzzy = (plugh + n - 1) / n;
The Ceiling function is for explicitly rounding up (towards positive infinity). There are many other variations of rounding (floor, truncate, round to even, round away from zero and so on), which can be found in this answer.
Found this which says that if you take the number to divide, add two, and divide by three you would get the correct answer. For example, 7/3 = 2.3, but (7+2)/3 = 3.

Rounding value to .5

There are the obvious quirks of Math.Round but is there a way to make Math.Round fulfill this type of manipulation for a rating system.
If greater than .0 and less than or equal to .5, display half a star
If greater than .5 and less than or equal to .0 display whole star
So obviously a half star would be .5 and a whole start would be the next whole value.
I don't know of a rounding method to go to half whole numbers.
Should I just write if statements to control my rounding?
**Edit/Solution
From the below answer I came up with.
double roundedRating = (Math.Ceiling(2 * currentRating)) / 2;
I'd recommend multiplying by two, performing Math.Ceiling, and dividing by two to get to the nearest half.
You're going to want to make sure that you end up performing your checks against integers, rather than floating point numbers.
Start by multiplying the number by 2. Continue doing this until it's an integer value (no value in the decimal part).
Now, continuously divide by 2 until you end up with a number that's less than or equal to the original number. If the result decimal part is greater than .0 and less than or equal to .5, display half a star. If it's greater than .5 and less than or equal to +.0, display a whole star.
Actually, go with matt's answer. ; )
Can this work?
Multiply the number by 10 e.g. 0.1x10, 0.2x10 to get n
Math.Ceil(n / 5) / 2
where n = 1, 2, 3 instead of - .1, .2, .3
examples:
1,2,3,4,5 = 1/2 = 0.5
6,7,8,9,10 = 2/2 = 1
11,12,13,14,15 = 3/2 = 1.5
If efficiency is no issue, the following approach could be used:
Number *= 10;
Number % 10 = remainder;
if(remainder <=5 && remainder != 0)
//Half star
else
//Whole star
However, that code is kinda ugly, but I think it gives you the general idea.
double roundedRating = (int)(currentRating * 2D + 0.999999999999999) / 2D

Why Math.Atan(Math.Tan(x)) != x?

If tan(x) = y and atan(y) = x why Math.Atan(Math.Tan(x)) != x?
I´m trying to calculate x in something like:
tan(2/x +3) = 5
so
atan(tan(2/x + 3) = atan(5)
and so on... but I´ve tried this:
double d = Math.Atan(Math.Tan(10));
and d != 10. Why?
The tangent function is periodic with period pi, and is invertible only if you restrict it to a subset of its domain over which it is injective. Usually the choice of such set is the open interval ]-pi/2, pi/2[, hence the arctan function will always return a point in that interval. In your case, 10 = 3*pi + 0.57522... Thus, the arctan of the tangent of 10 will return 0.57522...
Note that the arctan function, defined as above, is injective and defined over all the real numbers, hence the converse of your problem math.tan(math.atan(x)) == x
indeed holds for each x (except for numerical errors).
In order to deal with numerical errors, you should never perform comparisons between the results of floating point computations using == or !=. Use abs(number1 - number2) < epsilon // ==
abs(number1 - number2) >= epsilon // !=
instead, where epsilon is a small positive constant.
A graph might help explain why you are not getting the result you expected.
(source: wolfram.com)
http://mathworld.wolfram.com/Tangent.html
That shows the graph of Tan, but if you imagine reading off a value of x for a given y, (e.g. y = 0) then depending on which "strand" of Tan you read, you will get a different answer (-pi, 0, pi...). That's the point about Arctan(x) having more than one solution.
If arctan was restricted to only one of those strands, e.g. -pi/2 < x < pi/2 then Arctan(tan(x)) will return x providing you have accounted for floating point errors.
EDIT: However, according to http://msdn.microsoft.com/en-us/library/system.math.atan.aspx, the atan method already returns -pi/2 < x < pi/2 or NaN if your input is undefined. So the problem must soley be down to floating point rounding.
EDIT (F.R.): Added figure
I dont know any C#, but maths says that tan is not invertable, only in a small intervall.
e.g. tan(pi) = 0 and tan(0) = 0. When asking for atan(0) it could be 0 or pi (or every multiple of pi), so the result is in the range from -pi/2 .. pi/2.
Even if you start with an x in the invertable range i doesnt has to work, because of rounding errors with the floating points (it has not unlimmited precision).
tan-1(tan(x)) == x for all x in (-PI/2, PI/2).
Because the tangent function is periodic we need to normalize input angle. Math.Atan returns an angle, θ, measured in radians, such that -π/2 ≤ θ ≤ π/2, so it makes sense to normalize to that range (since it obviously won't anything within that range anyway):
double normalizedAngle = (angle + Math.PI / 2) % Math.PI - Math.PI / 2;
Doubles should be compared with some error margin. But in fact for this case Double.Epsilon is too small and "If you create a custom algorithm that determines whether two floating-point numbers can be considered equal, you must use a value that is greater than the Epsilon constant to establish the acceptable absolute margin of difference for the two values to be considered equal. (Typically, that margin of difference is many times greater than Epsilon.)" For instance, Math.Atan(Math.Tan(-0.49999632679501449)) + 0.49999632679501449 will be greater than Double.Epsilon for 1.1235582092889474E+307 times.
It might be helpful if you posted what you are trying to accomplish. I have recollections of discovering trig functions that handled the issue if what quadrant the inputs were in for me when I tried playing with angles, for example.
In general, when you are dealing with floating point numbers, you are dealing with approximations. There are numbers that cannot be represented exactly, and the tan and arctan operations are themselves only approximate.
If you want to compare floating point numbers, you need to ask if they are nearly equal, or equivalently, if the difference is less than some small value, and think carefully what you are doing.
Here is are some FAQS (for c++, but the idea is the same), that talk a bit about some of the oddities of floating point numbers:
FAQ 29.16
FAQ 29.17
FAQ 29.18
Edit: Looking at the other answers, I realise that the main problem is probably that tan isn't invertible, but the approximation issue is worth considering too, whenever you test floating point numbers for equality.
Looking at the .net documentation for Math.Atan, atan produces a value between -π/2 and ≤ π/2, which doesn't include 10. That I think is the usual range for arctan.
double d = Math.Atan(1) * (180 / Math.PI);
so d will be 45 in degrees

Categories

Resources