0

Is there an equivalent function in C# that works in same way as STR() in vfp https://msdn.microsoft.com/en-us/library/texae2db(v=vs.80).aspx

? str(111.666666,3,3) --> 112

? str(111.666666,2,3) --> ** error

? str(11.666666,2,3) --> 12

? str(0.666666,4,3) --> .667

? str(0.666666,8,3) --> 0.667 (ie 3 spaces from left plus the result)

mehwish
  • 199
  • 3
  • 15
  • 1
    Can you use it in a sentence? If you just have `STR(n)`, that looks like `n.ToString()`. – Ry- Sep 15 '17 at 08:50
  • Yeah the docs say it returns *the character equivalent of a numeric expression* so `ToString` will do the job, though it also allows for specifying the number of decimal places so probably a good idea to check out https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings – DavidG Sep 15 '17 at 08:57
  • [`STR(nExpression [, nLength [, nDecimalPlaces]])`](https://msdn.microsoft.com/en-us/library/texae2db(v=vs.80).aspx) is `nExpression.ToString()` plus [`nLength`](https://stackoverflow.com/q/3566830/1997232) and [`nDecimalPlaces`](https://stackoverflow.com/q/6951335/1997232) (as [format](https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings)). – Sinatr Sep 15 '17 at 09:04

2 Answers2

2

As mentioned in comments you can use .ToString() to convert numbers to string. You can use standart formats or custom formats in ToString. For example ToString("C") gives you a string like $123.46 or €123.46 for value of "123.46" based on your locale settings.

Or you can use custom formats like "0:#.##". You can use custom formats for different lengths or decimal places. For 2 decimal places "0:#.##" or for 3 decimal places "0:#.###".

For detailed explanations you can check documentation.

Standard numeric format strings: https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings

Custom numeric format strings: https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings

Custom method for STR

With the help of this link I wrote a quick sample. It works for your input but I did not test completely.

public static string STR(double d, int totalLen, int decimalPlaces)
{
    int floor = (int) Math.Floor(d);
    int length = floor.ToString().Length;
    if (length > totalLen)
        throw new NotImplementedException();
    if (totalLen - length < decimalPlaces)
        decimalPlaces =  totalLen - length;
    if (decimalPlaces < 0)
        decimalPlaces = 0;
    string str = Math.Round(d, decimalPlaces).ToString();
    if (str.StartsWith("0") && str.Length > 1 && totalLen - decimalPlaces - 1 <= 0)
        str = str.Remove(0,1);

    return str.Substring(0, str.Length >= totalLen ? totalLen : str.Length);
}
fofik
  • 998
  • 11
  • 17
  • I do not think it is simple as to string. – mehwish Sep 15 '17 at 09:13
  • It does various things based on the values passed, for example, if max length is less then the decimal places it will round the number, if max length is more than the result it does pad spaces – mehwish Sep 15 '17 at 09:14
  • Can you give some values as examples that ToString is not sufficient? – fofik Sep 15 '17 at 09:17
  • I have updated the question with some examples, thanks – mehwish Sep 15 '17 at 09:22
  • I believe you should do this in a custom function. Using floor length and decimal places count you can calculate a format. Or you can get a substring from the resulting string. Please check this question also. https://stackoverflow.com/questions/20403497/format-a-double-value-to-fit-into-a-maximum-string-size – fofik Sep 15 '17 at 10:16
  • Updated my answer to handle your samples. – fofik Sep 15 '17 at 10:57
0
public static string STR(object value, long totalLen = 0, long decimals = 0) {
  string result = string.Empty;
  try {

    if (value is string) {
      return (string)value;
    }

    var originalDecimals = decimals;
    int currentLen = (int)totalLen + 1;

    while (currentLen > totalLen) {
      string formatString = "{0:N";
      formatString += decimals.ToString();
      formatString += "}";

      result = string.Format(formatString, value);

      if (result.StartsWith("0") && result.Length > 1 && totalLen - decimals <= 1) {
        // STR(0.5, 3, 2) --> ".50"
        result = result.Remove(0, 1);
      }
      else if (result.StartsWith("-0") && result.Length > 2 && totalLen - decimals <= 2) {
        // STR(-0.5, 3, 2) --> "-.5"
        result = result.Remove(1, 1);
      }
      if (totalLen > 0&& result.Length < totalLen && (decimals == originalDecimals || decimals == 0)) {
        // STR(20, 3, 2) --> " 20"
        result = result.PadLeft((int)totalLen);
      }

      currentLen = result.Length;
      if (currentLen > totalLen) {
        decimals--;
        if (decimals < 0) {
          result = string.Empty.PadRight((int)totalLen, '*');
          break;
        }
      }
    }

    return result;
  }
  catch {
    result = "***";
  }

  return result;
}
  • **Some examples:** STR(0.5, 3, 2) --> ".50" STR(-0.5, 3, 2) --> "-.5" STR(20, 3, 2) --> " 20" STR(20, 4, 2) --> "20.0" STR(20, 5, 2) --> "20.00" STR(20, 7, 2) --> " 20.00" STR(78900, 10, 2) --> " 78,900.00" STR(99.99, 2, 0) --> "**" Use a format provider to get the formatting with the appropriate separator: _`result = string.Format(formatString, value);`_ --> _`result = string.Format(, formatString, value);`_ – Schnuffeline Sep 05 '19 at 14:35