How to implement a robust truncate method in C#? - c#

I know .NET has one built-in but it's an external call. Anyone knows why?
But the actual question is how to implement a truncate from scratch where the user will be able to specify how many digits to keep? Is multiplying a number by say 100 and then dividing it by the same amount enough? Or is there a better implementation?
Something like:
Truncate(12.3456789, 3);
// returns 12.345

The classic way:
var x = 1.2345678;
var tr = 4;
var truncated = (int) (x * Math.Pow(10, tr)) / Math.Pow(10, tr);
would give 1.2345;

You'd probably want to look at IEEE floating-point integers.
You can then use unsafe code to modify the numbers, like:
unsafe
{
double* pValue = &value;
var asLong = *(long*)pValue;
do whatever you want with asLong, e.g. bit-masking it, etc.;
}
As to the 'why': I have no idea, though the Shared Source CLI may provide clues. My guess would be that it might be because of performance optimizations.

Here is how I would do it. In C++, and I think in C# as well, you could get the integer part of a floating point number by casting it to an integer type.
double Truncate (double num, int dig)
{
if (dig > 15) dig = 15; // Don't overflow
long p = Math.Pow (10, dig);
// Save the integer part, so that we don't overflow
long integer_part = (long)num;
// Fractional part * 10^dig
double frac = (num - Convert.ToDouble(integer_part)) * p;
long frac_trunc = (long)frac;
// Final result
double result = Convert.ToDouble(integer_part) + (Convert.ToDouble(frac_trunc) / p);
return result;
}
Is multiplying a number by say 100 and then dividing it by the same
amount enough?
That should work, but be careful because with large numbers, or high number of digits, you can easily overflow, and it will give you weird results.

var result = Math.Round(12.3456789, 3);
Math.Round Method (Double, Int32)

It is not clear the reason you think that Truncate should keep the decmial value.
The default method within .NET is described by the following statement:
The integral part of d; that is, the number that remains after any
fractional digits have been discarded.
It seems like what you want to use is either to format the output string of an double/decmial value and/or use the Math.Round(double, int) function instead.
You could just use:
double num = 2.22939393; num = Convert.ToDouble(num.ToString("#0.000"));
From one of the duplicate questions:
public static decimal TruncateToDecimalPlace(this decimal numberToTruncate, int decimalPlaces)
{
decimal power = (decimal)(Math.Pow(10.0, (double)decimalPlaces));
return Math.Truncate((power * numberToTruncate)) / power;
}
I understand this still uses the Truncate method. I only provided this code since you wanted a Truncate method that would keep the decmial value of a number and the default built-in Truncate method does not.
You could always just use this:
Math.Round does NOT call the SplitFractionDouble from what I can tell
private static unsafe double InternalRound(double value, int digits, MidpointRounding mode) {
if (Abs(value) < doubleRoundLimit) {
Double power10 = roundPower10Double[digits];
value *= power10;
if (mode == MidpointRounding.AwayFromZero) {
double fraction = SplitFractionDouble(&value);
if (Abs(fraction) >= 0.5d) {
value += Sign(fraction);
}
}
else {
// On X86 this can be inlined to just a few instructions
value = Round(value);
}
value /= power10;
}
return value;
}
public static double Round(double value, int digits)
{
if ((digits < 0) || (digits > maxRoundingDigits))
throw new ArgumentOutOfRangeException("digits", Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits"));
return InternalRound(value, digits, MidpointRounding.ToEven);
}
public static double Round(double value, MidpointRounding mode) {
return Round(value, 0, mode);
}
public static double Round(double value, int digits, MidpointRounding mode) {
if ((digits < 0) || (digits > maxRoundingDigits))
throw new ArgumentOutOfRangeException("digits", Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits"));
if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) {
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumValue", mode, "MidpointRounding"), "mode");
}
return InternalRound(value, digits, mode);
}
public static Decimal Round(Decimal d) {
return Decimal.Round(d,0);
}
public static Decimal Round(Decimal d, int decimals) {
return Decimal.Round(d,decimals);
}
public static Decimal Round(Decimal d, MidpointRounding mode) {
return Decimal.Round(d, 0, mode);
}
public static Decimal Round(Decimal d, int decimals, MidpointRounding mode) {
return Decimal.Round(d, decimals, mode);
}
public static Decimal Floor(Decimal d) {
return Decimal.Floor(d);
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public static extern double Floor(double d);

Related

How to get the next decimal given a decimal/precision

I want to determine the next decimal after a certain decimal programmatically.
For example, I have the decimal 0.0000041
I want to programmatically generate 0.0000042 in a function.
If I ran the function again after running it with 0.0000042 the new number would be 0.0000043
If I ran the function with the decimal being 0.0000049 the new number would be 0.0000050 etc....
Is there a way to do this?
I do not know where to start or what references to look at to do something like this.
Thank you.
You seem to be looking for something like this: (Check below if you want to specify the precision manually)
static decimal GetNextDecimal(decimal input)
{
int count = BitConverter.GetBytes(decimal.GetBits(input)[3])[2];
return input + (1m / (decimal)Math.Pow(10, count));
}
Usage:
decimal num1 = 0.0000041m;
decimal num2 = 0.00002m;
decimal next = GetNextDecimal(num1);
decimal next2 = GetNextDecimal(num2);
Console.WriteLine(next);
Console.WriteLine(next2);
Output:
0.0000042
0.00003
I used a little help of this answer to get the number of the decimal places.
If you originally wanted to specify the precision manually, you can use the following instead:
static decimal GetNextDecimal(decimal input, int precision)
{
return input + (1m / (decimal)Math.Pow(10, precision));
}
..which allows you to do something like this:
decimal num1 = 0.003m;
decimal next = GetNextDecimal(num1, 3);
decimal next2 = GetNextDecimal(num1, 4);
Console.WriteLine(next);
Console.WriteLine(next2);
Output:
0.004
0.0031

Need only 2 digits after decimal point

I want my function to return value with only 2 decimal places. I have tried following code :
private static double CalculateSlabTax(int nSlabStartTaxable,
int nSlabEndTaxable,
float fSlabRate)
{
double dblSlabResult = 0;
try
{
dblSlabResult = (nSlabStartTaxable - nSlabEndTaxable) * fSlabRate;
dblSlabResult = Math.Round(dblSlabResult , 2);
return dblSlabResult;
}
catch (Exception)
{
return -1;
}
}
Expected output is : dblSlabResult = ####.## - two digits (eg. 1002.05)
Getting output as : eg. dblSlabResult = 1002.1
To represent use formatting. In your case exactly two digits after decimal point means "F2" format string
double source = 1234.56789;
// 1234.57
var result = source.ToString("F2");
Very simple. Try this
public double UptoTwoDecimalPoints(double num)
{
var totalCost = Convert.ToDouble(String.Format("{0:0.00}", num));
return totalCost;
}
The # character is an optional digit placeholder. Use 0 to enforce digits when converting to string:
string.Format("{0:#.##}", 1002.1) == "1002.1"
string.Format("{0:0.00}", 1002.1) == "1002.10"
Don't expect a specific count of digits when rounding float or double. They are just numbers, independent of their string format.
What inputs are you using? Math.Round should be working correctly, which suggests that the line above is returning a double with only 1 significant figure.

Incredibly huge and incredibly small numbers (not just integers) in C#

In C#, I need to work with very large (and very small) numbers, for which decimal and double are not accurate enough and BigInteger is not able to store a number's fractions.
I'd like to have the numbers to have as long components i.e. the characteristic and the mantissa, as memory (and preferably hard drive) space will allow.
Does someone have a class or is there a system type for a really big number.
I need to be able to add, subtract, divide, modulus, square, square-root, sin, cos, tan (and their inversions) and multiply the number. Pretty much the complete functionality of a standard Decimal/Double (in case I've missed any).
Infinity needn't be represented, but it would be a plus*!
An example of a very small number is:
0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
and examples of very large numbers are:
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
and
-1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
I'd prefer ToString() to return the number in the form described above. Scientific notation is acceptable, but by no means preferred.
Four most important requirements are:
the accuracy of the number
At least, basic maths operations can be
applied; multiply, division, addition and subtraction
The number must only be limited by the size of spare memory and harddrive.
Number must output as a string equivalent in the form
Characteristic, decimal point and then mantissa e.g. 100.23, 100 or
0.000000054
There should be support for reccurance in the mantissa
BigInteger is not an acceptable answer.
*If infinity is implimented, then I need only implement it as far as possible e.g. (infinity / infinity = 1), (0 / infinity = 0), etc.
Use BigInteger. It represents an arbitrarily large signed integer.
It doesn't fulfill the spec, but I would use BigInteger for integers and decimal for decimals.
BigInteger (in theory) has no upper or lower bounds.
Decimal is precise up to 28 significant figures
You may want to take a look at the BigRational class, which may be found on CodePlex.
It represents numbers as a ratio of two BigIntegers.
The ToString method doesn't meet your requirement as it formats the number as a ratio (numerator/denominator). But, since the source code is there, you can go wild implementing IFormattable.
You're asking for 2 things here that aren't currently possible in the same domain without losing some precision in your numbers. One thing is the infinity. And the other thing deals with the numerics. For example, unless you draw a line somewhere or you include some kind of pattern matching that tends towards a cutoff at a certain number, you cannot implement an "infinity".
But since you're going with really large numbers, and extremely precise small numbers, and since there is no known numeric data type that can support both, I recommend implementing your own. Just replicate the functionality of the numeric structures you already have and combine them to your needs.
My general idea is creating your own numeric data type that uses something like BigInteger for the integers and something like Decimals for the extremely precise numbers. Or you should also take a look at BigRational as they have some functionality for basic adding, subtracting, etc and they also have Numerator and Denominator properties.
The reason I'm going with Decimals over something else like Doubles is that Decimal types are fixed point and Doubles are floating point. Floating points are the reason why 0.1 + 0.2 = 0.30000000000000004, for example. But only consider this if you're completely implementing your own system.
tl;dr: Create your own class combining BigInteger and BigRational.
For my learning purposes I created class that can manage large number of digits, use it if you want. This class has some issues and I don't guarantee that it works 100% (but i test it for many scenarios and for all it was ok). Also division operator has performance issues (try to decrease divPrecision for more speed) and I don't have time right now to learn about division algorithms. I am certain there is more sophisticated (and probably much better) way to make such class but it is what I built in couple of hours based on your idea.
using System;
using System.Linq;
using System.Numerics;
namespace RealNumber
{
class RealNum
{
private BigInteger m = 0;
private int w = 0;
private static int divPrecision = 100000;
private static char[] trimStartChar = { '0', '-' };
private static char[] trimEndChars = { '.', ',' };
public RealNum()
{
}
public RealNum(BigInteger _m, int _w = 0 )
{
w = _w;
m = _m;
miniW();
}
public RealNum(string number)
{
number = number.Trim();
System.Text.RegularExpressions.Regex textValidator = new System.Text.RegularExpressions.Regex(#"^-?[0-9]+([,.][0-9]+)?$");
if (!textValidator.IsMatch(number))
{
throw new FormatException();
}
bool minSig = number.Contains('-');
number = number.TrimStart(trimStartChar);
if (number.Contains('.') || number.Contains(','))
{
number = number.TrimEnd(trimStartChar);
number = number.TrimEnd(trimEndChars);
}
if (string.IsNullOrEmpty(number))
{
return;
}
char[] splitChars = { '.', ',' };
string[] idnum = number.Split(splitChars, StringSplitOptions.None);
if (string.IsNullOrEmpty(idnum[0]))
idnum[0] = "0";
if(idnum.Length==1)
{
m = BigInteger.Parse(idnum[0]);
}
else
{
w = idnum[1].Length;
m = BigInteger.Parse(idnum[0]) * BigInteger.Pow(10, idnum[1].Length) + BigInteger.Parse(idnum[1]);
}
if (minSig)
m = -m;
miniW();
}
private void miniW()
{
while( m % (new BigInteger(10)) == 0 && m > 0 )
{
m = m / 10;
w--;
}
}
public override string ToString()
{
string num = m.ToString();
if (w > 0)
{
if(num.Length - w <= 0)
{
string zeros = new string('0', -num.Length + w + 1);
num = zeros + num;
}
num = num.Insert(num.Length - w, ".");
}
else if(w < 0)
{
string zeros = new string('0', -w);
num = num + zeros;
}
return num;
}
public static RealNum operator+ (RealNum a, RealNum b)
{
int wSub = a.w - b.w;
if(wSub<0)
{
wSub = -wSub;
a = System.Threading.Interlocked.Exchange(ref b, a);
}
return new RealNum(a.m + b.m * BigInteger.Pow(10, wSub), a.w);
}
public static RealNum operator -(RealNum a, RealNum b)
{
int wSub = a.w - b.w;
if (wSub < 0)
{
wSub = -wSub;
a = System.Threading.Interlocked.Exchange(ref b, a);
return new RealNum(b.m * BigInteger.Pow(10, wSub) - a.m, a.w);
}
return new RealNum(a.m - b.m * BigInteger.Pow(10, wSub), a.w);
}
public static RealNum operator *(RealNum a, RealNum b) =>
new RealNum(a.m * b.m, a.w+b.w);
public static RealNum operator /(RealNum a, RealNum b)
{
int precision = RealNum.divPrecision;
if (precision <= b.w)
precision = b.w+10;
int aSubSup = 0;
int aSub;
if (a.w < 0)
{
aSubSup = -a.w;
aSub = precision;
}
else
{
aSub = precision - a.w;
}
BigInteger am = a.m * BigInteger.Pow(10, aSubSup) * BigInteger.Pow(10, aSub);
return new RealNum(am/b.m, precision-b.w);
}
}
}

Getting Exact precision of decimal places from a double in .NET 3.5

Due to a requirement I need very exact precision of a double value to a 4 decimal places as follows:
double myDoubleValue = 50234.9489898997952932;
From the above, I need the output as 50234.9489. I DON'T want Rounding the number in this requirement.
I came across with "Math.Truncate(a * 100) / 100;". But really i'm not interested with this approach.
I'm looking for better approach very simple way something like using String.Format or with Regular Expressions etc.
double d = 50234.94895345345345;
var Expected_result = Double.Parse((Regex.Match(d.ToString(), "[+-]?\\d*.\\d{0,4}")).Value);
You would need to do this yourself. One of the possible solutions would be to use an extension method
public static class DoubleEx
{
public static double TruncateFraction(this double value, int fractionRound)
{
double factor = Math.Pow(10, fractionRound);
return Math.Truncate(value * factor) / factor;
}
}
And this is how to use it
double foo = 50234.9489898997952932;
double bar = foo.TruncateFraction(4);
Console.WriteLine(foo); //50234.9489898997952932
Console.WriteLine(bar); //50234.9489
Without regexes:
This works very much fine for any double combinations
using System.Globalization;
class Program
{
static void Main(string[] args)
{
double d = 50234.9489898997952932;
char probablyDot = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator[0];
string[] number = d.ToString().Split(probablyDot);
//Console.WriteLine(number[0] + probablyDot + number[1].Remove(4));
Console.WriteLine(number[0] + probablyDot + (number.Length >1 ? (number[1].Length>4? number[1].Substring(0,4):number[1]): "0000"));
//Output: 50234.9489
Console.ReadKey();
}
}
There are a lot of answers here that work with the input given in the question, but on testing them with a range of values, they all have limitations (see comments).
The only way I can see to achieve this with any decimal input is the following. It might not be a one liner, but it seems robust to me.
private static string TrimDecimalPlaces(double value, int numberOfDecimalPlaces)
{
string valueString = value.ToString();
if (!valueString.Contains(".")) return valueString;
int indexOfDot = valueString.IndexOf(".");
if ((indexOfDot + numberOfDecimalPlaces + 1) < valueString.Length)
{
return valueString.Remove(indexOfDot + numberOfDecimalPlaces + 1);
}
return valueString;
}
I've tested this with the following test data and the results are as expected:
1
1.1
1.11
1.111
1.1111
1.11111
1.111111
-1
-1.1
-1.11
-1.111
-1.1111
-1.11111
-1.111111

Random Number Between 2 Double Numbers

Is it possible to generate a random number between 2 doubles?
Example:
public double GetRandomeNumber(double minimum, double maximum)
{
return Random.NextDouble(minimum, maximum)
}
Then I call it with the following:
double result = GetRandomNumber(1.23, 5.34);
Any thoughts would be appreciated.
Yes.
Random.NextDouble returns a double between 0 and 1. You then multiply that by the range you need to go into (difference between maximum and minimum) and then add that to the base (minimum).
public double GetRandomNumber(double minimum, double maximum)
{
Random random = new Random();
return random.NextDouble() * (maximum - minimum) + minimum;
}
Real code should have random be a static member. This will save the cost of creating the random number generator, and will enable you to call GetRandomNumber very frequently. Since we are initializing a new RNG with every call, if you call quick enough that the system time doesn't change between calls the RNG will get seeded with the exact same timestamp, and generate the same stream of random numbers.
Johnny5 suggested creating an extension method. Here's a more complete code example showing how you could do this:
public static class RandomExtensions
{
public static double NextDouble(
this Random random,
double minValue,
double maxValue)
{
return random.NextDouble() * (maxValue - minValue) + minValue;
}
}
Now you can call it as if it were a method on the Random class:
Random random = new Random();
double value = random.NextDouble(1.23, 5.34);
Note that you should not create lots of new Random objects in a loop because this will make it likely that you get the same value many times in a row. If you need lots of random numbers then create one instance of Random and re-use it.
Watch out: if you're generating the random inside a loop like for example for(int i = 0; i < 10; i++), do not put the new Random() declaration inside the loop.
From MSDN:
The random number generation starts from a seed value. If the same
seed is used repeatedly, the same series of numbers is generated. One
way to produce different sequences is to make the seed value
time-dependent, thereby producing a different series with each new
instance of Random. By default, the parameterless constructor of the
Random class uses the system clock to generate its seed value...
So based on this fact, do something as:
var random = new Random();
for(int d = 0; d < 7; d++)
{
// Actual BOE
boes.Add(new LogBOEViewModel()
{
LogDate = criteriaDate,
BOEActual = GetRandomDouble(random, 100, 1000),
BOEForecast = GetRandomDouble(random, 100, 1000)
});
}
double GetRandomDouble(Random random, double min, double max)
{
return min + (random.NextDouble() * (max - min));
}
Doing this way you have the guarantee you'll get different double values.
I'm a bit late to the party but I needed to implement a general solution and it turned out that none of the solutions can satisfy my needs.
The accepted solution is good for small ranges; however, maximum - minimum can be infinity for big ranges. So a corrected version can be this version:
public static double NextDoubleLinear(this Random random, double minValue, double maxValue)
{
// TODO: some validation here...
double sample = random.NextDouble();
return (maxValue * sample) + (minValue * (1d - sample));
}
This generates random numbers nicely even between double.MinValue and double.MaxValue. But this introduces another "problem", which is nicely presented in this post: if we use such big ranges the values might seem too "unnatural". For example, after generating 10,000 random doubles between 0 and double.MaxValue all of the values were between 2.9579E+304 and 1.7976E+308.
So I created also another version, which generates numbers on a logarithmic scale:
public static double NextDoubleLogarithmic(this Random random, double minValue, double maxValue)
{
// TODO: some validation here...
bool posAndNeg = minValue < 0d && maxValue > 0d;
double minAbs = Math.Min(Math.Abs(minValue), Math.Abs(maxValue));
double maxAbs = Math.Max(Math.Abs(minValue), Math.Abs(maxValue));
int sign;
if (!posAndNeg)
sign = minValue < 0d ? -1 : 1;
else
{
// if both negative and positive results are expected we select the sign based on the size of the ranges
double sample = random.NextDouble();
var rate = minAbs / maxAbs;
var absMinValue = Math.Abs(minValue);
bool isNeg = absMinValue <= maxValue ? rate / 2d > sample : rate / 2d < sample;
sign = isNeg ? -1 : 1;
// now adjusting the limits for 0..[selected range]
minAbs = 0d;
maxAbs = isNeg ? absMinValue : Math.Abs(maxValue);
}
// Possible double exponents are -1022..1023 but we don't generate too small exponents for big ranges because
// that would cause too many almost zero results, which are much smaller than the original NextDouble values.
double minExponent = minAbs == 0d ? -16d : Math.Log(minAbs, 2d);
double maxExponent = Math.Log(maxAbs, 2d);
if (minExponent == maxExponent)
return minValue;
// We decrease exponents only if the given range is already small. Even lower than -1022 is no problem, the result may be 0
if (maxExponent < minExponent)
minExponent = maxExponent - 4;
double result = sign * Math.Pow(2d, NextDoubleLinear(random, minExponent, maxExponent));
// protecting ourselves against inaccurate calculations; however, in practice result is always in range.
return result < minValue ? minValue : (result > maxValue ? maxValue : result);
}
Some tests:
Here are the sorted results of generating 10,000 random double numbers between 0 and Double.MaxValue with both strategies. The results are displayed with using logarithmic scale:
Though the linear random values seem to be wrong at first glance the statistics show that none of them are "better" than the other: even the linear strategy has an even distribution and the average difference between the values are pretty much the same with both strategies.
Playing with different ranges showed me that the linear strategy gets to be "sane" with range between 0 and ushort.MaxValue with a "reasonable" minimum value of 10.78294704
(for ulong range the minimum value was 3.03518E+15; int: 353341). These are the same results of both strategies displayed with different scales:
Edit:
Recently I made my libraries open source, feel free to see the RandomExtensions.NextDouble method with the complete validation.
The simplest approach would simply generate a random number between 0 and the difference of the two numbers. Then add the smaller of the two numbers to the result.
You could use code like this:
public double getRandomNumber(double minimum, double maximum) {
return minimum + randomizer.nextDouble() * (maximum - minimum);
}
You could do this:
public class RandomNumbers : Random
{
public RandomNumbers(int seed) : base(seed) { }
public double NextDouble(double minimum, double maximum)
{
return base.NextDouble() * (maximum - minimum) + minimum;
}
}
What if one of the values is negative? Wouldn't a better idea be:
double NextDouble(double min, double max)
{
if (min >= max)
throw new ArgumentOutOfRangeException();
return random.NextDouble() * (Math.Abs(max-min)) + min;
}
Use a static Random or the numbers tend to repeat in tight/fast loops due to the system clock seeding them.
public static class RandomNumbers
{
private static Random random = new Random();
//=-------------------------------------------------------------------
// double between min and the max number
public static double RandomDouble(int min, int max)
{
return (random.NextDouble() * (max - min)) + min;
}
//=----------------------------------
// double between 0 and the max number
public static double RandomDouble(int max)
{
return (random.NextDouble() * max);
}
//=-------------------------------------------------------------------
// int between the min and the max number
public static int RandomInt(int min, int max)
{
return random.Next(min, max + 1);
}
//=----------------------------------
// int between 0 and the max number
public static int RandomInt(int max)
{
return random.Next(max + 1);
}
//=-------------------------------------------------------------------
}
See also : https://learn.microsoft.com/en-us/dotnet/api/system.random?view=netframework-4.8
About generating the same random number if you call it in a loop a nifty solution is to declare the new Random() object outside of the loop as a global variable.
Notice that you have to declare your instance of the Random class outside of the GetRandomInt function if you are going to be running this in a loop.
“Why is this?” you ask.
Well, the Random class actually generates pseudo random numbers, with the “seed” for the randomizer being the system time. If your loop is sufficiently fast, the system clock time will not appear different to the randomizer and each new instance of the Random class would start off with the same seed and give you the same pseudo random number.
Source is here : http://www.whypad.com/posts/csharp-get-a-random-number-between-x-and-y/412/
Random random = new Random();
double NextDouble(double minimum, double maximum)
{
return random.NextDouble()*random.Next(minimum,maximum);
}
If you need a random number in the range [double.MinValue; double.MaxValue]
// Because of:
double.MaxValue - double.MinValue == double.PositiveInfinity
// This will be equals to NaN or PositiveInfinity
random.NextDouble() * (double.MaxValue - double.MinValue)
Use instead:
public static class RandomExtensions
{
public static double NextDoubleInMinMaxRange(this Random random)
{
var bytes = new byte[sizeof(double)];
var value = default(double);
while (true)
{
random.NextBytes(bytes);
value = BitConverter.ToDouble(bytes, 0);
if (!double.IsNaN(value) && !double.IsInfinity(value))
return value;
}
}
}
Random rand = new Random();
rand.Next(1,5)/10; //Means between 0,1 and 0,5

Categories