-1

I have this small piece of code:

using System;
using System.Globalization;

namespace project
{
    class conditionalStatements
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Enter a number greater than 45.2");
            string answer = Console.ReadLine();
            decimal answer_decimal = Convert.ToDecimal(answer);
            // decimal answer_decimal = Decimal.Parse(answer);
            decimal compareValue = 45.2m;

            Console.WriteLine(answer_decimal);
            //prints 452

            if(Decimal.Compare(answer_decimal, compareValue) > 0){
                // stuff
            }
            else{
                // should enter here
            }
        }
    }
 }

The problem is that since both the method Convert.ToDecimal() and Decimal.Parse() ignore the dot notation of decimal values (or at least that's what's happening to me) the number is interpreted as 452 instead of 45.2. No matter how many dots I input. In fact, if I were to enter:

45......2

the converted value still would be converted to 452. Only if I use the comma, then the converted number is correctly interpreted as 45.2 and I am able to enter the else condition.

I did not change the NumberFormatInfo.CurrencyDecimalSeparator. I left it as default '.'

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68
  • 1
    What culture is associated with the thread? – Flydog57 Sep 01 '19 at 19:58
  • 4
    An advice not related to your current problem. Never try to use Convert.ToXXXX on user input. If the user types invalid numbers your code will raise an exception. In these contexts always use _decimal.TryParse_ – Steve Sep 01 '19 at 20:04

3 Answers3

0

Convert input string to decimal with a given culture that treats dot as decimal separator:

decimal answer_decimal = Convert.ToDecimal(answer, new CultureInfo("en-US"));
Rashid Ali
  • 587
  • 3
  • 13
  • The question states that the decimal separator (at least for currency) is already `'.'`. – Lance U. Matthews Sep 01 '19 at 22:13
  • This solves the problem with the dot. But what if I wanted to use both? Becuase in this case, now the same problem occurs with the comma. Isn't there a way to accept them both? Thank you very much for you help :) – the_hardworker43 Sep 02 '19 at 10:22
0

You could try something like the code below:

decimal answer_decimal; 
while(!decimal.TryParse(answer, out answer_decimal)){
    Console.WriteLine("Value entered could not be converted.");
}
decimal compareValue = 45.2m;

        Console.WriteLine(answer_decimal);
        //prints 452

        if(Decimal.Compare(answer_decimal, compareValue) > 0){
            // stuff
        }
        else{
            // should enter here
        }

This way you prevent the program from crashing if the conversion is not possible. If you want to use a specific culture you can do so by using an overload of decimal.TryParse as follows:

decimal.TryParse(answer, System.Globalization.NumberStyles.Any, new System.Globalization.CultureInfo("EN-us"), out answer_decimal);
0

Is your culture set to Dari?

I think the applicable NumberFormatInfo property would be NumberDecimalSeparator, not CurrencyDecimalSeparator. decimal.Parse(), called directly or via Convert.ToDecimal(), would have no idea currency is what's being parsed unless a NumberStyles value with one of the *Currency* flags were passed.

When an overload of decimal.Parse() is called that does not accept a NumberStyles parameter it defaults to NumberStyles.Number. This composite style includes the NumberStyles.AllowDecimalPoint style, the documentation for which states (emphasis mine)...

If the NumberStyles value includes the AllowCurrencySymbol flag and the parsed string includes a currency symbol, the decimal separator character is determined by the CurrencyDecimalSeparator property. Otherwise, the decimal separator character is determined by the NumberDecimalSeparator property.

Now, are there actually any cultures that use different decimal separators for numbers and currency? Let's find out...

CultureInfo.GetCultures(CultureTypes.AllCultures)
    .Where(culture => culture.NumberFormat.CurrencyDecimalSeparator != culture.NumberFormat.NumberDecimalSeparator);

On .NET Framework v4.7.2 that yields a small number of cultures...

fr-CH
kea
kea-CV
mr
mr-IN
prs
prs-AF
pt-CV

Tweaking that LINQ query to account for the specific behavior you're seeing (currency decimal separator is ".", number decimal separator is ",", number group separator is ".")...

CultureInfo.GetCultures(CultureTypes.AllCultures)
    .Where(culture => culture.NumberFormat.CurrencyDecimalSeparator == ".")
    .Where(culture => culture.NumberFormat.NumberDecimalSeparator == ",")
    .Where(culture => culture.NumberFormat.NumberGroupSeparator == ".");

...narrows it down to two Dari cultures...

prs
prs-AF

Sure enough, if I change my culture to Dari beforehand...

CultureInfo.CurrentCulture = new CultureInfo("prs");

...on my system your code behaves exactly as you described. If you don't want to use your culture's separators the solution, of course, is to specify at the system, thread, or method level a specific or custom culture with the separators you do want.

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68