Search Unity

Put spaces between numbers

Discussion in 'Scripting' started by Tutozz, Oct 16, 2018.

  1. Tutozz

    Tutozz

    Joined:
    Mar 16, 2018
    Posts:
    2
    Hello,
    I have a PlayerPref contain the money value and i want to know if it's possible to transform a int like that 1250000 to a string like that "1 250 000" simply in C#
    Thanks
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
  3. Tutozz

    Tutozz

    Joined:
    Mar 16, 2018
    Posts:
    2
    Thanks for your awnsers ;)
    This is my code:

    Code (CSharp):
    1.         Money = PlayerPrefs.GetInt("Money", 0);
    2.  
    3.         string MoneyPreArray = Money.ToString("N", CultureInfo.CreateSpecificCulture("fr-CA"));
    4.         int MoneyArray = MoneyPreArray.IndexOf(",");
    5.         if (MoneyArray > 0)
    6.             MoneyPreArray = MoneyPreArray.Substring(0, MoneyArray);
    7.  
    8.         MoneyCanvas.text =  MoneyPreArray + " $";
     
  4. If you accept additional advice...

    Don't call it Array, it's not.

    Also it's the other way around, usually the $ is on the beginning of the expression ($200 and not 200 $).
     
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,539
    Damn it... I've been doing it wrong all these years!

    ...

    In all seriousness, though I'm familiar with it going on front. But I really have written 100$ and the sort for most of my life, if there's no cents, and I'm in conversation typing (like forums and messengers). Mainly because it reads "100 dollars".

    [edit]

    Just googled...

    It appears French-Canadians do put $ on the end. Maybe OP is French-Canadian?
     
  6. Probably the Canadians stole your soul and influenced your usage of the dollar symbol! :p :D

    AFAIK, grammatically, the proper way of using the $ is to put it in the front of the sum. In the US. Other English speaking countries use it (sometimes) on the other way around. Now, of course, it's not a big deal, since the language is changing and all, I was just a little bit overzealous here (also assumed that the target is the US-version).
     
  7. Radical_boy

    Radical_boy

    Joined:
    Jan 30, 2021
    Posts:
    8
    I have stumbled across this when i was trying to convert big numbers like 1234567 into 1 234 567. I have looked through String Formatting but found a much easier way to do this.

    Code (CSharp):
    1.  
    2. int i = 1234567;
    3. string s = i.ToString("#,#").Replace(',' , ' ');
    4.  
    5. //basically formats the number with comma after 3 digits then replaces the commas with spaces
    6.  
     
    octaav and julesaintho like this.
  8. ChaoticForestCat

    ChaoticForestCat

    Joined:
    Nov 26, 2015
    Posts:
    18
    If use .ToString("#,0") then replace is not needed. The result will immediately be as it should be.
     
  9. Spy-Master

    Spy-Master

    Joined:
    Aug 4, 2022
    Posts:
    639
    You shouldn’t necropost, especially not with incorrect information. The result depends on the culture used for such operations. You would need to specify a culture that uses such behaviour or use the invariant culture for consistency with a follow-up Replace.
    Code (CSharp):
    1. using System;
    2. using System.Globalization;
    3. int i = 1234567;
    4. CultureInfo ci = CultureInfo.InvariantCulture;
    5. Console.WriteLine(i.ToString("#,#", ci).Replace(',' , ' '));
    6. // 1 234 567
    7. Console.WriteLine(i.ToString("#,0", ci));
    8. // 1,234,567
    9.  
     
    Ryiah and Nad_B like this.
  10. Nad_B

    Nad_B

    Joined:
    Aug 1, 2021
    Posts:
    730
    Yep, necroposting is bad. This is how it should be done and without any Replace:


    Code (CSharp):
    1. var number = 123456789;
    2.  
    3. // Cache and reuse this Culture to avoid allocations...
    4. var culture = new CultureInfo(CultureInfo.InvariantCulture.LCID);
    5. culture.NumberFormat.NumberGroupSeparator = " "; // Space as separator
    6. culture.NumberFormat.NumberDecimalSeparator = "."; // Not needed in integers
    7. culture.NumberFormat.NumberGroupSizes = new[] { 3 }; // Separate each 3 digits
    8.  
    9. Debug.Log(number.ToString("#,0", culture));
    10. // Output: 123 456 789
     
    Spy-Master and Ryiah like this.
  11. ChaoticForestCat

    ChaoticForestCat

    Joined:
    Nov 26, 2015
    Posts:
    18
    I'm concerned about finding a solution, not about problems with karma and other nonsense. Finding an answer to the question raised in this post turned out to be unexpectedly difficult. Therefore, I decided to share the result of my experiments. And it seems for good reason.

    Why is it necessary to specify a culture in this case? What happens if you don't specify anything?
     
  12. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,539
    Well...

    This statement only works if your current culture is a culture that uses spaces rather than commas to delimit numbers.

    Basically calling 'ToString' with only the format string, and not a cultureinfo, you're formatting using the current culture found at 'CultureInfo.CurrentCulture':
    https://learn.microsoft.com/en-us/d...ation.cultureinfo.currentculture?view=net-7.0

    Passing in a culture info, OR setting the CultureInfo.CurrentCulture globally, overrides the current culture allowing you to use a different culture's formatting.

    I don't know in what country you're located, but if you're in say a French speaking nation (I pick French because it's a common language that delimits with space rather than comma) you get the results you expect. But if you're in an English speaking nation using "#,0" does NOT give spaces, it gives commas. So does InvariantCulture. This is why @Spy-Master posted code that demonstrated using the InvariantCulture resulted in commas (note the commented lines in his code).
     
    ChaoticForestCat likes this.
  13. ChaoticForestCat

    ChaoticForestCat

    Joined:
    Nov 26, 2015
    Posts:
    18
    In this particular case, my goal was to make large numbers (1000000) more readable (1 000 000). And if for English speakers “,” is more familiar than “ ” then this does not seem to be a problem. Quite the contrary.
    Is there an easier way to get the desired result without diving into the localization jungle? Still, the option of prescribing separate cultural settings for only a few lines of numbers seems a little excessive.
     
  14. Nad_B

    Nad_B

    Joined:
    Aug 1, 2021
    Posts:
    730
    You didn't specify this in your question, you asked about using spaces and we all assumed that you ALWAYS wanted spaces as a numeric group separator, regardless of the current user Culture.

    If you just want your number to be readable in the current user Culture (i.e. their OS language), the solution is pretty easy:


    Code (CSharp):
    1. // N means Number. 0 is the number of decimals you want to display
    2. // in your case you don't want to display decimals so it's 0
    3. number.ToString("N0");
    4. // Output: English Culture: 12,345, French: 12 345, Arabic (Algeria): 12.345, India: 1,23,456...
    Here's the C# documentation for numbers formatting:
    https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings
     
    Last edited: Nov 13, 2023
    ChaoticForestCat likes this.
  15. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,539
    Note that only 3 people mentioned culture settings, 2 of which were in response to you, and those 2 mainly mentioned it to point out that your example code won't always work to get the result expected (spaces for every 3 digits) depending on the country of origin of the person running the application.

    Well, when using format strings the cultural settings become a necessity. It just is! That's how .Net deals with ToString and format strings!

    It's also the point of InvariantCulture, it allows you to force a specific low-biased culture info (it's not perfectly culture agnostic since that's not really a thing... it basically is English but with no origin country specifics).

    What I usually do is on start of my game I set the CurrentCulture overriding the user's local settings if I expect all my formatting to be exactly what I want it to be. Just on start say:

    Code (csharp):
    1. CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
    (or something to that effect... picking your desired culture)

    Now the first person to actually mention culture info back in 2018 did so by specifically picking a culture that uses spaces... in this case French-Canadian. They exploited that for a consistent method of formatting the way expected.

    Personally I wouldn't do that though if I very explicitly wanted spaces.

    ...

    Cause here's the thing we have 2 ways of approaching this problem:

    1) do we want spaces because we want spaces?

    2) do we want spaces because we want it readable to the local user's culture and I just biasly assumed spaces is that?

    Case in point you say:
    But that's the thing. You're saying "well if commas work for English speakers, than my code still works!" But that hinges on if the OP or anyone reading this thread is looking for option 2 rather than option 1.

    What if I SPECIFICALLY want spaces. Because in my game that's the theming I want. My game uses spaces for whatever reason (maybe my game is specifically aping French culture, or maybe my game is a fictional universe, or maybe I just find spaces aesthetically pleasing).

    If option 2 is what you want. The answer is as you said... just use "#,0" and allow the user's local culture info do the rest. You don't care what it looks like in the end, just that it follows the local user's culture. Which is exactly the entire point of the default ToString method.

    BUT, if it's option 1. Ok then you again have 2 choices:

    a) use format strings and coerce the culture info to follow the cultural formatting standards you want for your game

    b) don't use format strings and instead manually stringify your number.

    In option b, how is that done? Well... a lot of ways. I could think of 10 different ways off the top of my head to do it of varying efficiency and lines of code. (note that lines of code and efficiency aren't the same thing... ToString actually does a LOT under the hood).

    Here's a stackoverflow thread with a number of them:
    https://stackoverflow.com/questions/9932096/add-separator-to-string-at-every-n-characters

    This is also why back in 2018 I didn't really give an answer. People covered it by just offering up the documentation because well this is a far too nuanced conversation that just intrinsically involves culture!

    And to avoid the culture conversation needs explaining why the cultureinfo exists and why you'd need to avoid ToString format strings, and why now your code looks a bit convoluted. Otherwise people would be like "wait, why are you doing this convoluted thing instead of just using tostring and some format strings???"
     
    ChaoticForestCat likes this.
  16. ChaoticForestCat

    ChaoticForestCat

    Joined:
    Nov 26, 2015
    Posts:
    18
    Looking at these solutions, I begin to think that the option with cultural is not so difficult. But rather the opposite.
     
  17. ChaoticForestCat

    ChaoticForestCat

    Joined:
    Nov 26, 2015
    Posts:
    18
    The Indian version looks unexpectedly alien. This explains well why this whole complex localization system is needed. Although I thought that India is much closer to England in this regard. After all, their education system was originally created according to British standards.
     
  18. Nad_B

    Nad_B

    Joined:
    Aug 1, 2021
    Posts:
    730
    Because as far as I know they use something called Lakh as unit for big numbers (equals 100 000). For example they don't say 3 million rupees but 30 lakhs rupees.
     
    ChaoticForestCat likes this.
  19. As a Hungarian speaker (first language) who speaks some English (second language) and a very little bit of French (third language) I prefer when software don't try to switch to number formatting. Well, I specifically prefer numbers separated by spaces rather than coma.

    The reason is: in Hungarian we use comma as the English uses the dot (to separate the fractions from the whole numbers, so we use decimal comma), this is: 3,14 is the PI in Hungarian. In English it is 3.14 obviously (rounded up). And then in English we use the comma (usually) to separate whole number groups in large numbers, so 1,000,000 is one million. Well, in Hungarian we originally used an upper comma for this (kind of like apostrophe 1'000'000, well similar to an apostrophe but it isn't) then it was often simplified to an upper dot. But nowadays Hungary follows (more or less) the international standard (ISO 31-0).

    And I speak both Hungarian and English enough that instinctively, I try to parse the numbers in both ways I originally learned. Causing chaos and not really be able to parse most numbers instinctively anymore, because if I see a formatted number I slow down and try parsing separators to be sure I don't mix up decimal separator from thousand-separator.


    But in recent years, mostly because of the internet and international relations, the international standard is:
    - half-space
    - normal space or no separator, if half-space is not available (ASCII)
     
  20. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,011
    Well, here in germany it's actually the same :) Though we actually use the dot as the grouping character. So compared to english the dot and comma are swapped. I said it a couple of times in the past: when it comes to the decimal separator, the world is kinda split in half who's using a dot and who's using a comma.

    I visited hungary only once in my life about 20 years ago. It was an exchange program over two weeks with another school in hungary. We had a CNC and robotics course. Was a fun trip. I can't remember the name of the school, but it was in Zalaegerszeg.

    Ha, I just remembered that we got a certificate so I looked through my folders and I found it. The school was named after Munkácsy Mihály, located in the Gasparich street 24. The course was in June 2002

    During the CNC course we created a chess figure (a simple pawn) and I still have it:
    upload_2024-1-5_1-0-48.png
     
    Lurking-Ninja likes this.