Decimal Rounding Problem - c#

the following is my property where if we enter 45 then it appends 45.00 but then again it results in 45 because the value is converted from string. So what is the easiest way i can achieve this goal. Where if they enter 45 then it would result 45.00 in the value field;
public decimal Length
{
get { if (this is Detail)
return ((this as Detail).Length.ToString() == string.Empty)
? 0 : (this as Detail).Length; else return 0; }
set
{
if (this is Detail)
{
string val = string.Empty;
if (!value.ToString().Contains("."))
{
val = string.Format("{0}{1}", value.ToString(), ".00");
value =Math.Round(Convert.ToDecimal(val), 2);
}
else
value = Math.Round(value, 2);
(this as Detail).Length = (value.ToString().Trim() ==
string.Empty) ? 0 : value;
}
}
}

val = string.Format("{0:0.00}", value);

This has nothing to do with the property setter. You need to specify the string format in your GUI to round the numbers.
Also if (this is PersonalDetail) is a massive design flaw. Override the Length property in the PersonalDetail class instead. (not sure what the intent is with this property)

The problem is that 45m and 45.00m are the same thing, and since this is a decimal, it will always display "45" instead of "45.00" unless you use a string formatter every time you try to output it.
You could always make another property that does output what you want, such as:
public decimal Length { get; set; }
public string FormattedLength
{
get
{
return String.Format("{0:0.00}", this.Length);
}
}
On a side note I don't like this, but I believe it gets you more or less what you are looking for.

Related

How do I fix a DivideByZeroException

I am using DevExpress XAF Framework.
I have a Class with a lot of Persistent Alias Attributes that does some math on the properties. Here is an example of my code:
[PersistentAlias("ShortTermDebt + LongTermDebt / EquityTotal")]
public decimal DebtEquity
{
get
{
return decimal.Parse(EvaluateAlias("DebtEquity").ToString());
}
}
I have tried setting the Property to = 1
return DebtEquity = 1;
But all this does is reset the property to 1 on saving.
I have tried setting the Default Value in SQL Server for each property to 1. But this does not work either.
Basically, I have a Detailview that has a bunch of calculations on it. And when I want to create a NEW Detail View, I get a DivideByZeroException because of course a NEW Detail View/Object is not going to have any values. Any ideas how I can get around this?
If you can get the value of EquityTotal then you can check it for zero first, otherwise you can catch the exception.
Example with check value first:
[PersistentAlias("ShortTermDebt + LongTermDebt / EquityTotal")]
public decimal DebtEquity
{
get
{
if (EquityTotal == 0) return 0; // return 0 or whatever number you want when EquityTotal is equal to zero
return decimal.Parse(EvaluateAlias("DebtEquity").ToString());
}
}
Example with catch exception:
[PersistentAlias("ShortTermDebt + LongTermDebt / EquityTotal")]
public decimal DebtEquity
{
get
{
try
{
return decimal.Parse(EvaluateAlias("DebtEquity").ToString());
}
catch (DivideByZeroException)
{
return 0; // return 0 or whatever number you want when EquityTotal is equal to zero
}
}
}
As an alternative using pure criteria language syntax, you can use:
[PersistentAlias("Iif(EquityTotal > 0,ShortTermDebt+LongTermDebt/EquityTotal, 0)")]
public decimal DebtEquity
{
get => Convert.ToDecimal(EvaluateAlias(nameof(DebtEquity)))
}

A byte Property that should be 0 if the value would be negative?

I got a problem with a byte property.
I want the attribute to be 0 if an amount is subtracted that would set the number below 0.
My problem is that in a property I only get the value field where the calculation is already finished and the value is not negative but the amount that would have been negative subtracted from the max value of byte.
Changing the attribute type to sbyte is not option.
Is there any way to ensure that 4 minus 5 is 0 and not 255 without writing an explicit setter method and only using a getter property?
First, avoid byte for general integral use. Operating on int is faster, gives you more flexibility and byte will only save space if you pack them in, and even then the saving won't be significant until you've millions of such objects.
Now, you aren't clear where the "number that is subtracted is".
If the can't-be-negative rule is a matter of the state (rather than "it's negative really but displays as zero, and e.g. -3 plus 2 will still show zero because internally it's zero"), then enforce that rule at the point where the sutraction happens.
private void Subtract(int subtrahend)
{
value = Math.Max(value - subtrahend, 0);
}
If it should beinternally negative but display as zero then, just do that in the getter
public byte ByteForSomeReason
{
get { return Math.Max(value, 0); }
}
Or indeed, do so in a setter. What do you have against setters setting values, I would rather suspect that they'd be good at that.
How about something like this, where the backing property is an int:
private int m_TestValue;
public byte TestValue
{
get
{
if (m_TestValue < 0)
{
return 0;
}
else
{
return (byte)m_TestValue;
}
}
set {
m_TestValue = value;
}
}
Update
Thanks to 32bitkid, I now realize the above solution will not work because any negative value will be converted to a positive value prior to reaching the setter.
The only way to solve this, other than checking the value prior to assignment, is to change the data type of the property to an int, but then provide a byte property that provides the desired functionality.
For example:
public int TestValue {get; set; }
public byte TestValueAsByte
{
get
{
if (this.TestValue < 0)
{
return 0;
}
else
{
return (byte)this.TestValue;
}
}
set
{
this.TestValue = value;
}
}

How to make sure a zero is always at the end

I need to make sure that a double always ends with 0
6 = 6.0
5.9876577878 = 5.98765778780
I tried the format but did not bring the expected result.
How can this be done?
Not sure if the String.Format method allows you to do this. Here's something you can do though:
public static class DoubleUtils {
public static String EnsureEndsWithZero(this double value) {
String str = value.ToString();
if(!str.EndsWith("0")) {
if(str.Contains(".")) {
str += "0";
} else {
str += ".0";
}
}
return str;
}
}
Usage:
double val = 10.1;
Console.WriteLine(val.EnsureEndsWithZero());
Unless you're extremely liberal about how many zeros are at the end of the number (i.e. 1 OR MORE zeros is okay), then I think you'd have to check the resulting string to see if there's a zero after the decimal point, and add one or both if they aren't there.

TryParse failing with negative numbers

I'm having a problem getting TryParse to work correctly for me. I have a list of values that I am almost assured are valid (as they come from another component in our system) but I would like to make sure there is proper error handling in place.
Here is an example list of my values:
20.00
20.00
-150.00
And here is the method I originally wrote:
private decimal CalculateValue(IEnumerable<XElement> summaryValues)
{
decimal totalValue = 0;
foreach (XElement xElement in summaryValues)
{
decimal successful;
Decimal.TryParse(xElement.Value, out successful);
if (successful > 0)
totalValue += Decimal.Parse(xElement.Value);
}
return totalValue;
}
The variable 'successful' was returning false for -150.00, so I added NumberStyles:
private decimal CalculateValue(IEnumerable<XElement> summaryValues)
{
decimal totalValue = 0;
foreach (XElement xElement in summaryValues)
{
decimal successful;
Decimal.TryParse(xElement.Value, NumberStyles.AllowLeadingSign, null, out successful);
if (successful > 0)
totalValue += Decimal.Parse(xElement.Value, NumberStyles.AllowLeadingSign);
}
return totalValue;
}
However, now that I have the NumberStyles in there, none of the numbers will parse! I feel good about having IFormatProvider set to null as this is all within our system. Does anyone see what I may be doing wrong?
This is not how you are supposed to use TryParse.
TryParse returns a boolean (true/false), so your code above should be:
private decimal CalculateValue(IEnumerable<XElement> summaryValues)
{
decimal totalValue = 0;
foreach (XElement xElement in summaryValues)
{
decimal valueReturned;
bool successful = Decimal.TryParse(xElement.Value, out valueReturned);
if (successful)
totalValue += valueReturned;
}
return totalValue;
}
or more succinctly,
private decimal CalculateValue(IEnumerable<XElement> summaryValues)
{
decimal totalValue = 0;
foreach (XElement xElement in summaryValues)
{
decimal valueReturned;
if (Decimal.TryParse(xElement.Value, out valueReturned))
totalValue += valueReturned;
}
return totalValue;
}
Others are explaining how to do it right, but not really explaining what you're doing wrong.
Where you're using "successful" above isn't the success value, it's the actual number that is being parsed. So if you're parsing "-150.00" of course successful will be negative. The out value of TryParse is the actual parsed value and the boolean indicating whether the process was successful or not is the returned value. Using what you have to help understand would be something like:
string inputValue = "-150.00";
decimal numericValue;
bool isSucessful = Decimal.TryParse(inputValue , out numericValue);
In this case, isSuccessful will be TRUE, numericValue will be -150. When you're using user-provided values instead of the hardcoded one I used above you'll want to check:
if(isSuccessful)
{
// Do something with numericValue since we know it to be a valid decimal
}
else
{
// Inform User, throw exception, etc... as appropriate, Don't use numericValue because we know it's wrong.
}
The other answers have got the right idea with regard to the proper way to use Decimal.TryParse. However, if I were writing the method in question, I'd use LINQ to work with LINQ-to-XML objects:
private decimal CalculateValue(IEnumerable<XElement> summaryValues)
{
return summaryValues
.Sum(el =>
{
decimal value;
if (Decimal.TryParse(el.Value, out value))
return value;
return 0M;
});
}
This version works the exact same way, but it uses the Enumerable.Sum method to calculate the total. All I have to supply is an inline function that extracts decimal values from an XElement.
Came in from Google. Answer for me was the incoming culture was wrong - specifically in an incoming JSON file.
Use
totalValue += decimal.Parse(xElement.Value, NumberStyles.Any, CultureInfo.InvariantCulture);
or
bool successful = decimal.TryParse(xElement.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out value);
your successful is going to be negative for a negative value being parsed. your if (successful > 0) is what's tripping you up.
If they are almost positively going to be valid values, try using Convert.ToDecimal:
decimal val = Convert.ToDecimal(xElement.Value);
Otherwise, change your logic a bit to be more like:
decimal val;
if (Decimal.TryParse(xElement.Value, out val)){
// valid number
}
I would suggest you to tell XElement which node value it should look for as in:
XElement.Element("nodename").Value
Instead of XElement.Value. at least that is what I would do :)

how to truncate an double datatype value variable

i have an class
public class Score
{
public double marks { get; set; }
}
now in my code
List<Level1> Obj= new List<Level1>();
Score Object= new Score();
l1.marks=94.345454;
Obj.Add(Object)
// now whiling adding the object to list i need to trunacte the value to
94.34 and store in the list obj.
so that i need to get output has 94.34
how can i do it.
thanks in advance
prince
Keep the value as a double, and only format it on output.
string output = doubleValue.ToString("F2");
Source. As an example:
doubleNumber = -1898300.1987;
Console.WriteLine(doubleNumber.ToString("F1", CultureInfo.InvariantCulture));
// Displays -1898300.2
Console.WriteLine(doubleNumber.ToString("F3",
CultureInfo.CreateSpecificCulture("es-ES")));
// Displays -1898300,199
Notice the decimal comma on the last output as the culture is set to Spanish.
You could do this in the marks property setter:
value -= value % 0.01
this will subtract 0.005454 from value and so leave you with the correct number of decimal points (in this case, 2)
something like:
public class Score {
private double m_marks;
public double marks {
get { return m_marks; }
set { m_marks = value - (value % 0.01); }
}
}
You could use Math.Round(number, precision) as shown on msdn

Categories

Resources