Related
I was working on a factorial function, and factorial with big integers can get REALLY long.
For example, 200000! = 973350 digits long and if i just use ToString(), things take a very long time.
200000! takes longer to convert to string then actually compute it!
I've tried to set the factorial function to a Process, and then use ProcessorAffinity to pin the Thread to a specific core so that that core ONLY converts to string, but that just took exactly the same time.
Also, the reason I want to convert it to string is because I want to write the output (FactFile) to a text file.
String Conversion code:
using (Process proc = Process.GetCurrentProcess())
{
proc.ProcessorAffinity = (IntPtr)0x0003;
FactFile = Res.ToString(); //FactFile is Going to be the final string, Res is the Factorial.
}
here's my code for Factorial:
for (BigInteger i = 1; i < k; i++)
{
Res *= i; // Res is the number to Calculate the factorial of
}
200000! takes 15 seconds to compute, and then another 18 seconds to convert it to string (this can differ from cpu to cpu, I have an i7).
Reminder: What's the most efficient way to convert to string?
output:
Total Computation Time: 00:00:16.2007276
String Conversion Time: 00:00:19.4049292
Here is a 40% faster stringifier. It divides the big integer repeatedly with the number 10^10000, stringifies the remainder, and finally joins all the strings together. It can handle negative numbers also.
public static string ToDecimalString(this BigInteger value)
{
if (value == 0) return "0";
var digits = 10000;
var divider = BigInteger.Pow(10, digits);
var parts = new Stack<string>();
while (true)
{
BigInteger remainder;
value = BigInteger.DivRem(value, divider, out remainder);
if (value != 0)
{
parts.Push(BigInteger.Abs(remainder).ToString().PadLeft(digits, '0'));
}
else
{
parts.Push(remainder.ToString());
break;
}
}
return String.Join("", parts);
}
It can become slightly faster by offloading the stringifying of the remainders to a background thread. Unfortunately the slowest part of the algorithm (the call to BigInteger.DivRem) is not parallelizable.
public static string ToDecimalStringParallel(this BigInteger value)
{
if (value == 0) return "0";
var digits = 10000;
var divider = BigInteger.Pow(10, digits);
var remainders = new BlockingCollection<BigInteger>();
var parts = new ConcurrentStack<string>();
var task = Task.Run(() =>
{
foreach (var remainder in remainders.GetConsumingEnumerable())
{
parts.Push(BigInteger.Abs(remainder).ToString().PadLeft(digits, '0'));
}
});
while (true)
{
BigInteger remainder;
value = BigInteger.DivRem(value, divider, out remainder);
if (value != 0)
{
remainders.Add(remainder);
}
else
{
remainders.CompleteAdding();
task.Wait();
parts.Push(remainder.ToString());
break;
}
}
return String.Join("", parts);
}
For n! above n = 24, the result will have more digits than the value of input n.
That explosion of digits causes ToString to have to do more work than the factorial (n-1 multiplies vs more than n divides).
However because BigInteger operations take longer based on the magnitude of the numbers they work on, you can divide by a factor first, e.g. for your 200000! example:
var asString = Res.ToString()
Versus:
BigInteger[] bits = new BigInteger[2];
bits[0] = BigInteger.DivRem(Res, BigInteger.Pow(new BigInteger(10), 486675), out var remainder);
bits[1] = remainder;
var strs = new string[2];
System.Threading.Tasks.Parallel.For(0, 2, (i) =>
{
strs[i] = bits[i].ToString();
});
var asString = strs[0] + strs[1];
I found this to be 5 seconds faster but:
I had to choose a factor of 10^486675 to divide the digits equally - not sure how you'd do that in general
The initial DivRem takes 8 seconds
See also some existing attempts to speed up both factorial calculation and bigint to base 10 by breaking up the work.
The conclusion of the second one seemed to be.. don't convert large BigIntegers to base 10!
Lets say I have a value of 3.4679 and want 3.46, how can I truncate to two decimal places that without rounding up?
I have tried the following but all three give me 3.47:
void Main()
{
Console.Write(Math.Round(3.4679, 2,MidpointRounding.ToEven));
Console.Write(Math.Round(3.4679, 2,MidpointRounding.AwayFromZero));
Console.Write(Math.Round(3.4679, 2));
}
This returns 3.46, but just seems dirty some how:
void Main()
{
Console.Write(Math.Round(3.46799999999 -.005 , 2));
}
value = Math.Truncate(100 * value) / 100;
Beware that fractions like these cannot be accurately represented in floating point.
It would be more useful to have a full function for real-world usage of truncating a decimal in C#. This could be converted to a Decimal extension method pretty easy if you wanted:
public decimal TruncateDecimal(decimal value, int precision)
{
decimal step = (decimal)Math.Pow(10, precision);
decimal tmp = Math.Truncate(step * value);
return tmp / step;
}
If you need VB.NET try this:
Function TruncateDecimal(value As Decimal, precision As Integer) As Decimal
Dim stepper As Decimal = Math.Pow(10, precision)
Dim tmp As Decimal = Math.Truncate(stepper * value)
Return tmp / stepper
End Function
Then use it like so:
decimal result = TruncateDecimal(0.275, 2);
or
Dim result As Decimal = TruncateDecimal(0.275, 2)
Universal and fast method (without Math.Pow() / multiplication) for System.Decimal:
decimal Truncate(decimal d, byte decimals)
{
decimal r = Math.Round(d, decimals);
if (d > 0 && r > d)
{
return r - new decimal(1, 0, 0, false, decimals);
}
else if (d < 0 && r < d)
{
return r + new decimal(1, 0, 0, false, decimals);
}
return r;
}
Use the modulus operator:
var fourPlaces = 0.5485M;
var twoPlaces = fourPlaces - (fourPlaces % 0.01M);
result: 0.54
One issue with the other examples is they multiply the input value before dividing it. There is an edge case here that you can overflow decimal by multiplying first, an edge case, but something I have come across. It's safer to deal with the fractional part separately as follows:
public static decimal TruncateDecimal(this decimal value, int decimalPlaces)
{
decimal integralValue = Math.Truncate(value);
decimal fraction = value - integralValue;
decimal factor = (decimal)Math.Pow(10, decimalPlaces);
decimal truncatedFraction = Math.Truncate(fraction * factor) / factor;
decimal result = integralValue + truncatedFraction;
return result;
}
In .NET Core 3.0 and later Math.Round and Decimal.Round can truncate digits through the new MidpointRounding.ToZero. For positive numbers, MidpointRounding.ToNegativeInfinity has the same effect while for negative numbers the equivalent is MidpointRounding.ToPositiveInfinity.
These lines:
Console.WriteLine(Math.Round(3.4679, 2,MidpointRounding.ToZero));
Console.WriteLine(Math.Round(3.9999, 2,MidpointRounding.ToZero));
Console.WriteLine(Math.Round(-3.4679, 2,MidpointRounding.ToZero));
Console.WriteLine(Math.Round(-3.9999, 2,MidpointRounding.ToZero));
Produce :
3.46
3.99
-3.46
-3.99
I will leave the solution for decimal numbers.
Some of the solutions for decimals here are prone to overflow (if we pass a very large decimal number and the method will try to multiply it).
Tim Lloyd's solution is protected from overflow but it's not too fast.
The following solution is about 2 times faster and doesn't have an overflow problem:
public static class DecimalExtensions
{
public static decimal TruncateEx(this decimal value, int decimalPlaces)
{
if (decimalPlaces < 0)
throw new ArgumentException("decimalPlaces must be greater than or equal to 0.");
var modifier = Convert.ToDecimal(0.5 / Math.Pow(10, decimalPlaces));
return Math.Round(value >= 0 ? value - modifier : value + modifier, decimalPlaces);
}
}
[Test]
public void FastDecimalTruncateTest()
{
Assert.AreEqual(-1.12m, -1.129m. TruncateEx(2));
Assert.AreEqual(-1.12m, -1.120m. TruncateEx(2));
Assert.AreEqual(-1.12m, -1.125m. TruncateEx(2));
Assert.AreEqual(-1.12m, -1.1255m.TruncateEx(2));
Assert.AreEqual(-1.12m, -1.1254m.TruncateEx(2));
Assert.AreEqual(0m, 0.0001m.TruncateEx(3));
Assert.AreEqual(0m, -0.0001m.TruncateEx(3));
Assert.AreEqual(0m, -0.0000m.TruncateEx(3));
Assert.AreEqual(0m, 0.0000m.TruncateEx(3));
Assert.AreEqual(1.1m, 1.12m. TruncateEx(1));
Assert.AreEqual(1.1m, 1.15m. TruncateEx(1));
Assert.AreEqual(1.1m, 1.19m. TruncateEx(1));
Assert.AreEqual(1.1m, 1.111m. TruncateEx(1));
Assert.AreEqual(1.1m, 1.199m. TruncateEx(1));
Assert.AreEqual(1.2m, 1.2m. TruncateEx(1));
Assert.AreEqual(0.1m, 0.14m. TruncateEx(1));
Assert.AreEqual(0, -0.05m. TruncateEx(1));
Assert.AreEqual(0, -0.049m. TruncateEx(1));
Assert.AreEqual(0, -0.051m. TruncateEx(1));
Assert.AreEqual(-0.1m, -0.14m. TruncateEx(1));
Assert.AreEqual(-0.1m, -0.15m. TruncateEx(1));
Assert.AreEqual(-0.1m, -0.16m. TruncateEx(1));
Assert.AreEqual(-0.1m, -0.19m. TruncateEx(1));
Assert.AreEqual(-0.1m, -0.199m. TruncateEx(1));
Assert.AreEqual(-0.1m, -0.101m. TruncateEx(1));
Assert.AreEqual(0m, -0.099m. TruncateEx(1));
Assert.AreEqual(0m, -0.001m. TruncateEx(1));
Assert.AreEqual(1m, 1.99m. TruncateEx(0));
Assert.AreEqual(1m, 1.01m. TruncateEx(0));
Assert.AreEqual(-1m, -1.99m. TruncateEx(0));
Assert.AreEqual(-1m, -1.01m. TruncateEx(0));
}
This is an old question, but many anwsers don't perform well or overflow for big numbers. I think D. Nesterov answer is the best one: robust, simple and fast. I just want to add my two cents.
I played around with decimals and also checked out the source code. From the public Decimal (int lo, int mid, int hi, bool isNegative, byte scale) constructor documentation.
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.
Knowing this, my first approach was to create another decimal whose scale corresponds to the decimals that I wanted to discard, then truncate it and finally create a decimal with the desired scale.
private const int ScaleMask = 0x00FF0000;
public static Decimal Truncate(decimal target, byte decimalPlaces)
{
var bits = Decimal.GetBits(target);
var scale = (byte)((bits[3] & (ScaleMask)) >> 16);
if (scale <= decimalPlaces)
return target;
var temporalDecimal = new Decimal(bits[0], bits[1], bits[2], target < 0, (byte)(scale - decimalPlaces));
temporalDecimal = Math.Truncate(temporalDecimal);
bits = Decimal.GetBits(temporalDecimal);
return new Decimal(bits[0], bits[1], bits[2], target < 0, decimalPlaces);
}
This method is not faster than D. Nesterov's and it is more complex, so I played around a little bit more. My guess is that having to create an auxiliar decimal and retrieving the bits twice is making it slower. On my second attempt, I manipulated the components returned by Decimal.GetBits(Decimal d) method myself. The idea is to divide the components by 10 as many times as needed and reduce the scale. The code is based (heavily) on the Decimal.InternalRoundFromZero(ref Decimal d, int decimalCount) method.
private const Int32 MaxInt32Scale = 9;
private const int ScaleMask = 0x00FF0000;
private const int SignMask = unchecked((int)0x80000000);
// Fast access for 10^n where n is 0-9
private static UInt32[] Powers10 = new UInt32[] {
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000
};
public static Decimal Truncate(decimal target, byte decimalPlaces)
{
var bits = Decimal.GetBits(target);
int lo = bits[0];
int mid = bits[1];
int hi = bits[2];
int flags = bits[3];
var scale = (byte)((flags & (ScaleMask)) >> 16);
int scaleDifference = scale - decimalPlaces;
if (scaleDifference <= 0)
return target;
// Divide the value by 10^scaleDifference
UInt32 lastDivisor;
do
{
Int32 diffChunk = (scaleDifference > MaxInt32Scale) ? MaxInt32Scale : scaleDifference;
lastDivisor = Powers10[diffChunk];
InternalDivRemUInt32(ref lo, ref mid, ref hi, lastDivisor);
scaleDifference -= diffChunk;
} while (scaleDifference > 0);
return new Decimal(lo, mid, hi, (flags & SignMask)!=0, decimalPlaces);
}
private static UInt32 InternalDivRemUInt32(ref int lo, ref int mid, ref int hi, UInt32 divisor)
{
UInt32 remainder = 0;
UInt64 n;
if (hi != 0)
{
n = ((UInt32)hi);
hi = (Int32)((UInt32)(n / divisor));
remainder = (UInt32)(n % divisor);
}
if (mid != 0 || remainder != 0)
{
n = ((UInt64)remainder << 32) | (UInt32)mid;
mid = (Int32)((UInt32)(n / divisor));
remainder = (UInt32)(n % divisor);
}
if (lo != 0 || remainder != 0)
{
n = ((UInt64)remainder << 32) | (UInt32)lo;
lo = (Int32)((UInt32)(n / divisor));
remainder = (UInt32)(n % divisor);
}
return remainder;
}
I haven't performed rigorous performance tests, but on a MacOS Sierra 10.12.6, 3,06 GHz Intel Core i3 processor and targeting .NetCore 2.1 this method seems to be much faster than D. Nesterov's (I won't give numbers since, as I have mentioned, my tests are not rigorous). It is up to whoever implements this to evaluate whether or not the performance gains pay off for the added code complexity.
Would ((long)(3.4679 * 100)) / 100.0 give what you want?
would this work for you?
Console.Write(((int)(3.4679999999*100))/100.0);
If you don't worry too much about performance and your end result can be a string, the following approach will be resilient to floating precision issues:
string Truncate(double value, int precision)
{
if (precision < 0)
{
throw new ArgumentOutOfRangeException("Precision cannot be less than zero");
}
string result = value.ToString();
int dot = result.IndexOf('.');
if (dot < 0)
{
return result;
}
int newLength = dot + precision + 1;
if (newLength == dot + 1)
{
newLength--;
}
if (newLength > result.Length)
{
newLength = result.Length;
}
return result.Substring(0, newLength);
}
Here is an extension method:
public static decimal? TruncateDecimalPlaces(this decimal? value, int places)
{
if (value == null)
{
return null;
}
return Math.Floor((decimal)value * (decimal)Math.Pow(10, places)) / (decimal)Math.Pow(10, places);
} // end
Here is my implementation of TRUNC function
private static object Tranc(List<Expression.Expression> p)
{
var target = (decimal)p[0].Evaluate();
// check if formula contains only one argument
var digits = p.Count > 1
? (decimal) p[1].Evaluate()
: 0;
return Math.Truncate((double)target * Math.Pow(10, (int)digits)) / Math.Pow(10, (int)digits);
}
what about this?
Function TruncateDecimal2(MyValue As Decimal) As Decimal
Try
Return Math.Truncate(100 * MyValue) / 100
Catch ex As Exception
Return Math.Round(MyValue, 2)
End Try
End Function
Apart from the above solutions,there is another way we can achieve .
decimal val=23.5678m,finalValue;
//take the decimal part
int decimalPos = val.ToString().IndexOf('.');
string decimalPart = val.ToString().Substring(decimalPosition+1,val.ToString().Length);
//will result.56
string wholePart=val.ToString().Substring(0,decimalPos-1);
//concantinate and parse for decimal.
string truncatedValue=wholePart+decimalPart;//"23.56"
bool isDecimal=Decimal.tryParse(truncatedValue,out finalValue);//finalValue=23.56
Under some conditions this may suffice.
I had a decimal value of
SubCent = 0.0099999999999999999999999999M that tends to format to |SubCent:0.010000| via string.Format("{0:N6}", SubCent ); and many other formatting choices.
My requirement was not to round the SubCent value, but not log every digit either.
The following met my requirement:
string.Format("SubCent:{0}|",
SubCent.ToString("N10", CultureInfo.InvariantCulture).Substring(0, 9));
Which returns the string : |SubCent:0.0099999|
To accommodate the value having an integer part the following is a start.
tmpValFmt = 567890.0099999933999229999999M.ToString("0.0000000000000000000000000000");
decPt = tmpValFmt.LastIndexOf(".");
if (decPt < 0) decPt = 0;
valFmt4 = string.Format("{0}", tmpValFmt.Substring(0, decPt + 9));
Which returns the string :
valFmt4 = "567890.00999999"
This is what i did:
c1 = a1 - b1;
d1 = Math.Ceiling(c1 * 100) / 100;
subtracting two inputted numbers without rounding up or down the decimals.
because the other solutions does not work for me.
don't know if it will work for others, i just want to share this :)
Hope it works tho for those who's finding solution to a problem similar to mine. Thanks
PS: i'm a beginner so feel free to point out something on this. :D
this is good if you're actually dealing with money, cause of the cents right? it only have 2 decimal places and rounding it is a no no.
public static decimal TruncateDecimalPlaces(this decimal value, int precision)
{
try
{
step = (decimal)Math.Pow(10, precision);
decimal tmp = Math.Truncate(step * value);
return tmp / step;
}
catch (OverflowException)
{
step = (decimal)Math.Pow(10, -1 * precision);
return value - (value % step);
}
}
my favorite is
var myvalue = 54.301012345;
var valueiwant = myvalue.toString("0.00");
//result => "54.30"
//additional
var valueiwant2 = myvalue.toString("0.##");
//result => "54.3" // without zero
function to truncate any decimal number without rounding
public static double round(double d, byte p)
{
return Math.Truncate(d * Math.Pow(10, p)) / Math.Pow(10, p);
}
i am using this function to truncate value after decimal in a string variable
public static string TruncateFunction(string value)
{
if (string.IsNullOrEmpty(value)) return "";
else
{
string[] split = value.Split('.');
if (split.Length > 0)
{
string predecimal = split[0];
string postdecimal = split[1];
postdecimal = postdecimal.Length > 6 ? postdecimal.Substring(0, 6) : postdecimal;
return predecimal + "." + postdecimal;
}
else return value;
}
}
public static void ReminderDigints(decimal? number, out decimal? Value, out decimal? Reminder)
{
Reminder = null;
Value = null;
if (number.HasValue)
{
Value = Math.Floor(number.Value);
Reminder = (number - Math.Truncate(number.Value));
}
}
decimal? number= 50.55m;
ReminderDigints(number, out decimal? Value, out decimal? Reminder);
Actually you want 3.46 from 3.4679 .
This is only representation of characters.So there is nothing to do with math function.Math function is not intended to do this work.
Simply use the following code.
Dim str1 As String
str1=""
str1 ="3.4679"
Dim substring As String = str1.Substring(0, 3)
' Write the results to the screen.
Console.WriteLine("Substring: {0}", substring)
Or
Please use the following code.
Public function result(ByVal x1 As Double) As String
Dim i as Int32
i=0
Dim y as String
y = ""
For Each ch as Char In x1.ToString
If i>3 then
Exit For
Else
y + y +ch
End if
i=i+1
Next
return y
End Function
The above code can be modified for any numbers Put the following
code in a button click event
Dim str As String
str= result(3.4679)
MsgBox("The number is " & str)
what about
var i = Math.Truncate(number);
var r = i + Math.Truncate((number - i) * 100) / 100;
I have some fields returned by a collection as
2.4200
2.0044
2.0000
I want results like
2.42
2.0044
2
I tried with String.Format, but it returns 2.0000 and setting it to N0 rounds the other values as well.
I ran into the same problem but in a case where I do not have control of the output to string, which was taken care of by a library. After looking into details in the implementation of the Decimal type (see http://msdn.microsoft.com/en-us/library/system.decimal.getbits.aspx),
I came up with a neat trick (here as an extension method):
public static decimal Normalize(this decimal value)
{
return value/1.000000000000000000000000000000000m;
}
The exponent part of the decimal is reduced to just what is needed. Calling ToString() on the output decimal will write the number without any trailing 0. E.g.
1.200m.Normalize().ToString();
Is it not as simple as this, if the input IS a string? You can use one of these:
string.Format("{0:G29}", decimal.Parse("2.0044"))
decimal.Parse("2.0044").ToString("G29")
2.0m.ToString("G29")
This should work for all input.
Update Check out the Standard Numeric Formats I've had to explicitly set the precision specifier to 29 as the docs clearly state:
However, if the number is a Decimal and the precision specifier is omitted, fixed-point notation is always used and trailing zeros are preserved
Update Konrad pointed out in the comments:
Watch out for values like 0.000001. G29 format will present them in the shortest possible way so it will switch to the exponential notation. string.Format("{0:G29}", decimal.Parse("0.00000001",System.Globalization.CultureInfo.GetCultureInfo("en-US"))) will give "1E-08" as the result.
In my opinion its safer to use Custom Numeric Format Strings.
decimal d = 0.00000000000010000000000m;
string custom = d.ToString("0.#########################");
// gives: 0,0000000000001
string general = d.ToString("G29");
// gives: 1E-13
I use this code to avoid "G29" scientific notation:
public static string DecimalToString(this decimal dec)
{
string strdec = dec.ToString(CultureInfo.InvariantCulture);
return strdec.Contains(".") ? strdec.TrimEnd('0').TrimEnd('.') : strdec;
}
EDIT: using system CultureInfo.NumberFormat.NumberDecimalSeparator :
public static string DecimalToString(this decimal dec)
{
string sep = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
string strdec = dec.ToString(CultureInfo.CurrentCulture);
return strdec.Contains(sep) ? strdec.TrimEnd('0').TrimEnd(sep.ToCharArray()) : strdec;
}
Use the hash (#) symbol to only display trailing 0's when necessary. See the tests below.
decimal num1 = 13.1534545765;
decimal num2 = 49.100145;
decimal num3 = 30.000235;
num1.ToString("0.##"); //13.15%
num2.ToString("0.##"); //49.1%
num3.ToString("0.##"); //30%
I found an elegant solution from http://dobrzanski.net/2009/05/14/c-decimaltostring-and-how-to-get-rid-of-trailing-zeros/
Basically
decimal v=2.4200M;
v.ToString("#.######"); // Will return 2.42. The number of # is how many decimal digits you support.
A very low level approach, but I belive this would be the most performant way by only using fast integer calculations (and no slow string parsing and culture sensitive methods):
public static decimal Normalize(this decimal d)
{
int[] bits = decimal.GetBits(d);
int sign = bits[3] & (1 << 31);
int exp = (bits[3] >> 16) & 0x1f;
uint a = (uint)bits[2]; // Top bits
uint b = (uint)bits[1]; // Middle bits
uint c = (uint)bits[0]; // Bottom bits
while (exp > 0 && ((a % 5) * 6 + (b % 5) * 6 + c) % 10 == 0)
{
uint r;
a = DivideBy10((uint)0, a, out r);
b = DivideBy10(r, b, out r);
c = DivideBy10(r, c, out r);
exp--;
}
bits[0] = (int)c;
bits[1] = (int)b;
bits[2] = (int)a;
bits[3] = (exp << 16) | sign;
return new decimal(bits);
}
private static uint DivideBy10(uint highBits, uint lowBits, out uint remainder)
{
ulong total = highBits;
total <<= 32;
total = total | (ulong)lowBits;
remainder = (uint)(total % 10L);
return (uint)(total / 10L);
}
This is simple.
decimal decNumber = Convert.ToDecimal(value);
return decNumber.ToString("0.####");
Tested.
Cheers :)
Depends on what your number represents and how you want to manage the values: is it a currency, do you need rounding or truncation, do you need this rounding only for display?
If for display consider formatting the numbers are x.ToString("")
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx and
http://msdn.microsoft.com/en-us/library/0c899ak8.aspx
If it is just rounding, use Math.Round overload that requires a MidPointRounding overload
http://msdn.microsoft.com/en-us/library/ms131274.aspx)
If you get your value from a database consider casting instead of conversion:
double value = (decimal)myRecord["columnName"];
This will work:
decimal source = 2.4200m;
string output = ((double)source).ToString();
Or if your initial value is string:
string source = "2.4200";
string output = double.Parse(source).ToString();
Pay attention to this comment.
Trying to do more friendly solution of DecimalToString (https://stackoverflow.com/a/34486763/3852139):
private static decimal Trim(this decimal value)
{
var s = value.ToString(CultureInfo.InvariantCulture);
return s.Contains(CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator)
? Decimal.Parse(s.TrimEnd('0'), CultureInfo.InvariantCulture)
: value;
}
private static decimal? Trim(this decimal? value)
{
return value.HasValue ? (decimal?) value.Value.Trim() : null;
}
private static void Main(string[] args)
{
Console.WriteLine("=>{0}", 1.0000m.Trim());
Console.WriteLine("=>{0}", 1.000000023000m.Trim());
Console.WriteLine("=>{0}", ((decimal?) 1.000000023000m).Trim());
Console.WriteLine("=>{0}", ((decimal?) null).Trim());
}
Output:
=>1
=>1.000000023
=>1.000000023
=>
how about this:
public static string TrimEnd(this decimal d)
{
string str = d.ToString();
if (str.IndexOf(".") > 0)
{
str = System.Text.RegularExpressions.Regex.Replace(str.Trim(), "0+?$", " ");
str = System.Text.RegularExpressions.Regex.Replace(str.Trim(), "[.]$", " ");
}
return str;
}
You can just set as:
decimal decNumber = 23.45600000m;
Console.WriteLine(decNumber.ToString("0.##"));
The following code could be used to not use the string type:
int decimalResult = 789.500
while (decimalResult>0 && decimalResult % 10 == 0)
{
decimalResult = decimalResult / 10;
}
return decimalResult;
Returns 789.5
In case you want to keep decimal number, try following example:
number = Math.Floor(number * 100000000) / 100000000;
Here is an Extention method I wrote, it also removes dot or comma if it`s the last character (after the zeros were removed):
public static string RemoveZeroTail(this decimal num)
{
var result = num.ToString().TrimEnd(new char[] { '0' });
if (result[result.Length - 1].ToString() == "." || result[result.Length - 1].ToString() == ",")
{
return result.Substring(0, result.Length - 1);
}
else
{
return result;
}
}
To remove trailing zero's from a string variable dateTicks, Use
return new String(dateTicks.Take(dateTicks.LastIndexOf(dateTicks.Last(v => v != '0')) + 1).ToArray());
Additional Answer:
In a WPF Application using XAML you could use
{Binding yourDecimal, StringFormat='#,0.00#######################'}
The above answer will preserve the zero in some situations so you could still return 2.00 for example
{Binding yourDecimal, StringFormat='#,0.#########################'}
If you want to remove ALL trailing zeros, adjust accordingly.
The following code will be able to remove the trailing 0's. I know it's the hard way but it works.
private static string RemoveTrailingZeros(string input)
{
for (int i = input.Length - 1; i > 0; i-- )
{
if (!input.Contains(".")) break;
if (input[i].Equals('0'))
{
input= input.Remove(i);
}
else break;
}
return input;
}
string.Format("{0:G29}", decimal.Parse("2.00"))
string.Format("{0:G29}", decimal.Parse(Your_Variable))
try this code:
string value = "100";
value = value.Contains(".") ? value.TrimStart('0').TrimEnd('0').TrimEnd('.') : value.TrimStart('0');
Very simple answer is to use TrimEnd(). Here is the result,
double value = 1.00;
string output = value.ToString().TrimEnd('0');
Output is 1
If my value is 1.01 then my output will be 1.01
try like this
string s = "2.4200";
s = s.TrimStart("0").TrimEnd("0", ".");
and then convert that to float
I would like to generate a code like goo.gl and jsfiddle websites (http://jsfiddle.net/XzKvP/).
I tried different things that give me too large of a guid, a repeating alphanumeric code, etc.
I'm thinking I should be able to generate an alphanumeric code based on the Primary Key in my database table. This way it will be non-repeating? The PK is an auto-incremented integer by 1. But not sure that's how it should be done.
I want the code to look random, but it does NOT have to be.
For example, I do NOT want item 1234 in my database to be BCDE and the 1235 item to be BCDF.
Examples:
Notice how the url http://jsfiddle.net/XzKvP/ has a unique 5 character code XzKvP associated to the page. I want to be able to generate the same type of code.
goo.gl does it too: http://goo.gl/UEhtg has UEhtg
How is this done?
The solutions based on a random substring are no good because the outputs will collide. It may happen prematurely (with bad luck), and it will eventually happen when the list of generated values grows large. It doesn't even have to be that large for the probability of collisions to become high (see birthday attack).
What's good for this problem is a pseudo random permutation between the incrementing ID and its counterpart that will be shown in the URL. This technique guarantees that a collision is impossible, while still generating into an output space that is as small as the input space.
Implementation
I suggest this C# version of a Feistel cipher with 32 bits blocks, 3 rounds and a round function that is inspired by pseudo-random generators.
private static double RoundFunction(uint input)
{
// Must be a function in the mathematical sense (x=y implies f(x)=f(y))
// but it doesn't have to be reversible.
// Must return a value between 0 and 1
return ((1369 * input + 150889) % 714025) / 714025.0;
}
private static uint PermuteId(uint id)
{
uint l1=(id>>16)&65535;
uint r1=id&65535;
uint l2, r2;
for (int i = 0; i < 3; i++)
{
l2 = r1;
r2 = l1 ^ (uint)(RoundFunction(r1) * 65535);
l1 = l2;
r1 = r2;
}
return ((r1 << 16) + l1);
}
To express the permuted ID in a base62 string:
private static string GenerateCode(uint id)
{
return ToBase62(PermuteId(id));
}
The Base62 function is the same as the previous answer except that is takes uint instead of int (otherwise these functions would have to be rewritten to deal with negative values).
Customizing the algorithm
RoundFunction is the secret sauce of the algorithm. You may change it to a non-public version, possibly including a secret key. The Feistel network has two very nice properties:
even if the supplied RoundFunction is not reversible, the algorithm guarantees that PermuteId() will be a permutation in the mathematical sense (wich implies zero collision).
changing the expression inside the round function even lightly will change drastically the list of final output values.
Beware that putting something too trivial in the round expression would ruin the pseudo-random effect, although it would still work in terms of uniqueness of each PermuteId output. Also, an expression that wouldn't be a function in the mathematical sense would be incompatible with the algorithm, so for instance anything involving random() is not allowed.
Reversability
In its current form, the PermuteId function is its own inverse, which means that:
PermuteId(PermuteId(id))==id
So given a short string produced by the program, if you convert it back to uint with a FromBase62 function, and give that as input to PermuteId(), that will return the corresponding initial ID. That's pretty cool if you don't have a database to store the [internal-ID / shortstring] relationships: they don't actually need to be stored!
Producing even shorter strings
The range of the above function is 32 bits, that is about 4 billion values from 0 to 2^32-1. To express that range in base62, 6 characters are needed.
With only 5 characters, we could hope to represent at most 62^5 values, which is a bit under 1 billion. Should the output string be limited to 5 characters, the code should be tweaked as follows:
find N such that N is even and 2^N is as high as possible but lower than 62^5. That's 28, so our real output range that fits in 62^5 is going to be 2^28 or about 268 million values.
in PermuteId, use 28/2=14 bits values for l1 and r1 instead of 16 bits, while being careful to not ignore a single bit of the input (which must be less than 2^28).
multiply the result of RoundFunction by 16383 instead of 65535, to stay within the 14 bits range.
at the end of PermuteId, recombine r1 and l1 to form a 14+14=28 bits value instead of 32.
The same method could be applied for 4 characters, with an output range of 2^22, or about 4 million values.
What does it look like
In the version above, the first 10 produced strings starting with id=1 are:
cZ6ahF
3t5mM
xGNPN
dxwUdS
ej9SyV
cmbVG3
cOlRkc
bfCPOX
JDr8Q
eg7iuA
If I make a trivial change in the round function, that becomes:
ey0LlY
ddy0ak
dDw3wm
bVuNbg
bKGX22
c0s5GZ
dfNMSp
ZySqE
cxKH4b
dNqMDA
You can think of the five-letter code as a number in base-62 notation: your "digits" are 26 lowercase and 26 uppercase letters, and digits from 0 to 9. (26+26+10) digits in total. Given a number from 0 to 62^5 (which equals 916132832) (say, your primary key) you can do the conversion to a five-digit base-62 as follows:
private static char Base62Digit(int d) {
if (d < 26) {
return (char)('a'+d);
} else if (d < 52) {
return (char)('A'+d-26);
} else if (d < 62) {
return (char)('0'+d-52);
} else {
throw new ArgumentException("d");
}
}
static string ToBase62(int n) {
var res = "";
while (n != 0) {
res = Base62Digit(n%62) + res;
n /= 62;
}
return res;
}
private static int Base62Decode(char c) {
if (c >= '0' && c <= '9') {
return 52 + c - '0';
} else if (c >= 'A' && c <= 'Z') {
return 26 + c - 'A';
} else if (c >= 'a' && c <= 'z') {
return c - 'a';
} else {
throw new ArgumentException("c");
}
}
static int FromBase62(string s) {
return s.Aggregate(0, (current, c) => current*62 + Base62Decode(c));
}
Here is how to generate cryptographically strong random numbers (you need to add a reference to System.Security):
private static readonly RNGCryptoServiceProvider crypto =
new RNGCryptoServiceProvider();
private static int NextRandom() {
var buf = new byte[4];
crypto.GetBytes(buf);
return buf.Aggregate(0, (p, v) => (p << 8) + v) & 0x3FFFFFFF;
}
This is what I ended up doing
(Updated since Daniel Vérité's answer):
class Program
{
private static double RoundFunction(uint input)
{
// Must be a function in the mathematical sense (x=y implies f(x)=f(y))
// but it doesn't have to be reversible.
// Must return a value between 0 and 1
return ((1369 * input + 150889) % 714025) / 714025.0;
}
private static char Base62Digit(uint d)
{
if (d < 26)
{
return (char)('a' + d);
}
else if (d < 52)
{
return (char)('A' + d - 26);
}
else if (d < 62)
{
return (char)('0' + d - 52);
}
else
{
throw new ArgumentException("d");
}
}
private static string ToBase62(uint n)
{
var res = "";
while (n != 0)
{
res = Base62Digit(n % 62) + res;
n /= 62;
}
return res;
}
private static uint PermuteId(uint id)
{
uint l1 = (id >> 16) & 65535;
uint r1 = id & 65535;
uint l2, r2;
for (int i = 0; i < 3; i++)
{
l2 = r1;
r2 = l1 ^ (uint)(RoundFunction(r1) * 65535);
l1 = l2;
r1 = r2;
}
return ((r1 << 16) + l1);
}
private static string GenerateCode(uint id)
{
return ToBase62(PermuteId(id));
}
static void Main(string[] args)
{
Console.WriteLine("testing...");
try
{
for (uint x = 1; x < 1000000; x += 1)
{
Console.Write(GenerateCode(x) + ",");
}
}
catch (Exception err)
{
Console.WriteLine("error: " + err.Message);
}
Console.WriteLine("");
Console.WriteLine("Press 'Enter' to continue...");
Console.Read();
}
}
Given a potentially huge integer value (in C# string format), I want to be able to generate its hex equivalent. Normal methods don't apply here as we are talking arbitrarily large numbers, 50 digits or more. The techniques I've seen which use a technique like this:
// Store integer 182
int decValue = 182;
// Convert integer 182 as a hex in a string variable
string hexValue = decValue.ToString("X");
// Convert the hex string back to the number
int decAgain = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);
won't work because the integer to convert is too large.
For example I need to be able to convert a string like this:
843370923007003347112437570992242323
to its hex equivalent.
these don't work:
C# convert integer to hex and back again
How to convert numbers between hexadecimal and decimal in C#?
Oh, that's easy:
var s = "843370923007003347112437570992242323";
var result = new List<byte>();
result.Add( 0 );
foreach ( char c in s )
{
int val = (int)( c - '0' );
for ( int i = 0 ; i < result.Count ; i++ )
{
int digit = result[i] * 10 + val;
result[i] = (byte)( digit & 0x0F );
val = digit >> 4;
}
if ( val != 0 )
result.Add( (byte)val );
}
var hex = "";
foreach ( byte b in result )
hex = "0123456789ABCDEF"[ b ] + hex;
Use a BigInteger to store the integer, and than use the .ToString("X") on that object.
Example:
var number = BigInteger.Parse("843370923007003347112437570992242323");
string hexValue = number.ToString("X");
This is however limited to .NET 4 and later. But Jens A. pointed to a BigInteger class on codeproject that class contains a method called ToHexString so that would work for a < .NET 4 scenario.
As Jens said, take a look at the BigInt implementation on Code Project. Even if they don't have a function to convert to hex, you could easily write a function to do it yourself as long as this BigInt has a divide and modulo operation (I don't think it has a modulo function, so you would also need to write modulo yourself)
heh nice solutions for dec<->hex conversions here on stackoverflow so far ,... but i needed (gigantic int . gigantic fraction) with almost none precision lost so i modded all codes i found with my already done codes and here is some i can share (without big int/real lib usage)
//---------------------------------------------------------------------------
AnsiString str_hex2dec(const AnsiString &hex)
{
char c;
AnsiString dec="",s;
int i,j,l,ll,cy,val;
int i0,i1,i2,i3,sig;
sig=+1; l=hex.Length();
if (l) { c=hex[l]; if (c=='h') l--; if (c=='H') l--; }
i0=0; i1=l; i2=0; i3=l;
for (i=1;i<=l;i++) // scan for parts of number
{
char c=hex[i];
if (c=='-') sig=-sig;
if ((c=='.')||(c==',')) i1=i-1;
if ((c>='0')&&(c<='9')) { if (!i0) i0=i; if ((!i2)&&(i>i1)) i2=i; }
if ((c>='A')&&(c<='F')) { if (!i0) i0=i; if ((!i2)&&(i>i1)) i2=i; }
if ((c>='a')&&(c<='f')) { if (!i0) i0=i; if ((!i2)&&(i>i1)) i2=i; }
}
l=0; s=""; if (i0) for (i=i0;i<=i1;i++)
{
c=hex[i];
if ((c>='0')&&(c<='9')) c-='0';
else if ((c>='A')&&(c<='F')) c-='A'-10;
else if ((c>='a')&&(c<='f')) c-='A'-10;
for (cy=c,j=1;j<=l;j++)
{
val=(s[j]<<4)+cy;
s[j]=val%10;
cy =val/10;
}
while (cy>0)
{
l++;
s+=char(cy%10);
cy/=10;
}
}
if (s!="")
{
for (j=1;j<=l;j++) { c=s[j]; if (c<10) c+='0'; else c+='A'-10; s[j]=c; }
for (i=l,j=1;j<i;j++,i--) { c=s[i]; s[i]=s[j]; s[j]=c; }
dec+=s;
}
if (dec=="") dec="0";
if (sig<0) dec="-"+dec;
if (i2)
{
dec+='.';
s=hex.SubString(i2,i3-i2+1);
l=s.Length();
for (i=1;i<=l;i++)
{
c=s[i];
if ((c>='0')&&(c<='9')) c-='0';
else if ((c>='A')&&(c<='F')) c-='A'-10;
else if ((c>='a')&&(c<='f')) c-='A'-10;
s[i]=c;
}
ll=((l*1234)>>10); // num of decimals to compute
for (cy=0,i=1;i<=ll;i++)
{
for (cy=0,j=l;j>=1;j--)
{
val=s[j];
val*=10;
val+=cy;
s[j]=val&15;
cy=val>>4;
}
dec+=char(cy+'0');
for (;;)
{
if (!l) break;;
if (s[l]) break;
l--;
}
if (!l) break;;
}
}
return dec;
}
//---------------------------------------------------------------------------
AnsiString str_dec2hex(AnsiString dec)
{
AnsiString hex=""; BYTE a,b;
int i,j,i0,i1,i2,i3,l,sig;
sig=+1; l=dec.Length();
i0=0; i1=l; i2=0; i3=l;
for (i=1;i<=l;i++) // scan for parts of number
{
char c=dec[i];
if (c=='-') sig=-sig;
if ((c=='.')||(c==',')) i1=i-1;
if ((c>='0')&&(c<='9')) { if (!i0) i0=i; if ((!i2)&&(i>i1)) i2=i; }
}
if (i0) for (;i1>=i0;i1=j-1)// process integer part /16
{
for (a=0,j=i0,i=i0;i<=i1;i++)
{
a*=10; a+=dec[i]-'0';
if (a<16) { if (j>i0){ dec[j]='0'; j++; } continue; }
b=a>>4; a=a&15;
if (b>10) { dec[j]='1'; j++; b-=10; }
dec[j]=b+'0'; j++;
}
if ((!a)&&(hex=="")) continue;
if (a<10) a+='0'; else a+='A'-10;
hex=AnsiString(char(a))+hex;
}
if (hex=="") hex="0";
if ((i2)&&(i2<=i3)) // process fractional part *16
for (hex+=".",j=i3-i2+2;j;j--)
{
for (a=0,b=0,i=i3;i>=i2;i--)
{
a=dec[i]-'0';
b+=a<<4; dec[i]=(b%10)+'0'; b/=10;
}
if (b<10) b+='0'; else b+='A'-10;
hex+=char(b);
}
if (sig<0) hex="-"+hex; hex+="h";
return hex;
}
//---------------------------------------------------------------------------
P.S. if you need to cut off fractional digits (to format numbers) than you have to round by most significant digit of the cutted part.
rounding abs up in dec mode if digit >='5'
rounding abs up in hex mode if digit >='8'
if you wonder what means this line:
ll=((l*1234)>>10); // num of decimals to compute
than it compute the number of fractional digits that match input string precision (1.205 decimal fractional digits per hexadecimal fractional digit). This ratio i get by empirical measurement of accuracy up to 1280 bits per fractional part of number. for simplicity
1e-l can be stored with max error up to 1e-(l+1). This ratio is almost constant (except for low fractional digit values (<16 digits) so this formula can be used for any larger num of digits safely. In low input digit values is output wrong max by 1 (>8 digits) or max 2 (<=8 digits) digits