Reputation: 113
This is the code below for converting numbers to words. What is the exactly problem ? Everything is great in English but in my country (Romania) there is different spelling let's make that clear in a few examples :
Ex. 1 - English, One dollar,One thousand, One hundred, Two hundred that's how you write Romanian, Un dollar, O mie, O suta, Doua Sute, Trei Sute, there is a plural changing on the words, In English you use One for everything almost in Romanian this changes and I don't know how to fix it this plural.Thank you
private static string[] _ones =
{
"",
"unu",
"doua",
"trei",
"patru",
"cinci",
"sase",
"sapte",
"opt",
"noua"
};
private static string[] _teens =
{
"zece",
"unsprezece",
"doisprezece",
"treisprezece",
"paisprezece",
"cincisprezece",
"saisprezece",
"saptisprezece",
"optsprezece",
"nouasprezece"
};
private static string[] _tens =
{
"",
"zece",
"douazeci",
"treizeci",
"patruzeci",
"cincizeci",
"saizeci",
"saptezeci",
"optzeci",
"nouazeci"
};
// US Nnumbering:
private static string[] _thousands =
{
"",
"mie",
"milion",
"miliard",
"trilion",
"catralion"
};
string digits, temp;
bool showThousands = false;
bool allZeros = true;
// Use StringBuilder to build result
StringBuilder builder = new StringBuilder();
// Convert integer portion of value to string
digits = ((long)value).ToString();
// Traverse characters in reverse order
for (int i = digits.Length - 1; i >= 0; i--)
{
int ndigit = (int)(digits[i] - '0');
int column = (digits.Length - (i + 1));
// Determine if ones, tens, or hundreds column
switch (column % 3)
{
case 0: // Ones position
showThousands = true;
if (i == 0)
{
// First digit in number (last in loop)
temp = String.Format("{0} ", _ones[ndigit]);
}
else if (digits[i - 1] == '1')
{
// This digit is part of "teen" value
temp = String.Format("{0} ", _teens[ndigit]);
// Skip tens position
i--;
}
else if (ndigit != 0)
{
// Any non-zero digit
temp = String.Format("{0} ", _ones[ndigit]);
}
else
{
// This digit is zero. If digit in tens and hundreds
// column are also zero, don't show "thousands"
temp = String.Empty;
// Test for non-zero digit in this grouping
if (digits[i - 1] != '0' || (i > 1 && digits[i - 2] != '0'))
showThousands = true;
else
showThousands = false;
}
// Show "thousands" if non-zero in grouping
if (showThousands)
{
if (column > 0)
{
temp = String.Format("{0}{1}{2}",
temp,
_thousands[column / 3],
allZeros ? " " : ", ");
}
// Indicate non-zero digit encountered
allZeros = false;
}
builder.Insert(0, temp);
break;
case 1: // Tens column
if (ndigit > 0)
{
temp = String.Format("{0}{1}",
_tens[ndigit],
(digits[i + 1] != '0') ? " si " : " ");
builder.Insert(0, temp);
}
break;
case 2: // Hundreds column
if (ndigit > 0)
{
temp = String.Format("{0} sute ", _ones[ndigit]);
builder.Insert(0, temp);
}
break;
}
}
builder.AppendFormat("lei si {0:00} bani", (value - (long)value) * 100);
// Capitalize first letter
return String.Format("{0}{1}",
Char.ToUpper(builder[0]),
builder.ToString(1, builder.Length - 1));
Upvotes: 0
Views: 165
Reputation: 74267
You need to track the [various] plural forms of numbers.
Most languages has just two grammatical numbers: singular and plural and only differentiate between 1 and many when talking about things.
Some languages, Romanian apparently included, have three grammatical numbers: singular, dual and plural, and so differentiate between 1, 2 and many of something.
English is a little weird because in talking about numbers we don't generally apply grammatical number to the words: we say "one hundred" , "two hundred" and "three hundred". However, in keeping with our long tradition of inconsistent usage, there are certain contexts and scenarios in which it is permissible, and one might, say something like "7 billions dead". But I digress.
As a result, the "usual" algorithm for converting numbers to words (3,792 to "three thousand, seven hundred and ninety-two") doesn't really care about the grammatical number of the names of the digit groupings or the values.
For languages that do, you need something like a 2-dimensional matrix with the rows mapping the part's value to the word and the columns providing the proper word form for the specified grammatical number (singular, dual, plural).
Upvotes: 0
Reputation: 5258
You've stated there are only 2 possible conditions for hundreds and thousands:
Hundreds: 1 = suta / more than 1 = sute
Thousands: 1 = mie / more than 1 = mii
In both cases, if singular, then "o" is used instead of "unu" to mean "one"
Based on this you can easily add the right conditions in the code.
I personally would refactor this code but since that's not the point here, I've included a solution for you.
Hundreds:
Instead of
case 2: // Hundreds column
if (ndigit > 0)
{
temp = String.Format("{0} sute ", _ones[ndigit]);
builder.Insert(0, temp);
}
Add the condition to check on digit and use sute or suta:
case 2: // Hundreds column
if (ndigit > 0)
{
temp = String.Format("{0} {1} ", ndigit == 1 ? "o" : _ones[ndigit], ndigit == 1 ? "suta" : "sute");
builder.Insert(0, temp);
}
Thousands
Instead of ...
// Show "thousands" if non-zero in grouping
if (showThousands)
{
if (column > 0)
{
temp = String.Format("{0}{1}{2}",
temp,
_thousands[column / 3],
allZeros ? " " : ", ");
}
// Indicate non-zero digit encountered
allZeros = false;
}
Should be:
// Show "thousands" if non-zero in grouping
if (showThousands)
{
if (column > 0)
{
bool isFirstThoussand = _thousands[column / 3] == _thousands[1] && ndigit == 1;
temp = String.Format("{0}{1}{2}",
isFirstThoussand ? "o " : temp,
isFirstThoussand ? _thousands[1] : "mii",
allZeros ? " " : ", ");
}
// Indicate non-zero digit encountered
allZeros = false;
}
...
This will yield the result desired based on your current parameters.
Here's your whole code (with the updates from this answer) and some test stuff:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RomanianNumberToWords
{
class Program
{
private static string[] _ones =
{
"",
"unu",
"doua",
"trei",
"patru",
"cinci",
"sase",
"sapte",
"opt",
"noua"
};
private static string[] _teens =
{
"zece",
"unsprezece",
"doisprezece",
"treisprezece",
"paisprezece",
"cincisprezece",
"saisprezece",
"saptisprezece",
"optsprezece",
"nouasprezece"
};
private static string[] _tens =
{
"",
"zece",
"douazeci",
"treizeci",
"patruzeci",
"cincizeci",
"saizeci",
"saptezeci",
"optzeci",
"nouazeci"
};
// US Nnumbering:
private static string[] _thousands =
{
"",
"mie",
"milion",
"miliard",
"trilion",
"catralion"
};
static string MakeWordFromNumbers(decimal value)
{
string digits, temp;
bool showThousands = false;
bool allZeros = true;
// Use StringBuilder to build result
StringBuilder builder = new StringBuilder();
// Convert integer portion of value to string
digits = ((long)value).ToString();
// Traverse characters in reverse order
for (int i = digits.Length - 1; i >= 0; i--)
{
int ndigit = (int)(digits[i] - '0');
int column = (digits.Length - (i + 1));
// Determine if ones, tens, or hundreds column
switch (column % 3)
{
case 0: // Ones position
showThousands = true;
if (i == 0)
{
// First digit in number (last in loop)
temp = String.Format("{0} ", _ones[ndigit]);
}
else if (digits[i - 1] == '1')
{
// This digit is part of "teen" value
temp = String.Format("{0} ", _teens[ndigit]);
// Skip tens position
i--;
}
else if (ndigit != 0)
{
// Any non-zero digit
temp = String.Format("{0} ", _ones[ndigit]);
}
else
{
// This digit is zero. If digit in tens and hundreds
// column are also zero, don't show "thousands"
temp = String.Empty;
// Test for non-zero digit in this grouping
if (digits[i - 1] != '0' || (i > 1 && digits[i - 2] != '0'))
showThousands = true;
else
showThousands = false;
}
// Show "thousands" if non-zero in grouping
if (showThousands)
{
if (column > 0)
{
bool isFirstThoussand = _thousands[column / 3] == _thousands[1] && ndigit == 1;
temp = String.Format("{0}{1}{2}",
isFirstThoussand ? "o " : temp,
isFirstThoussand ? _thousands[1] : "mii",
allZeros ? " " : ", ");
}
// Indicate non-zero digit encountered
allZeros = false;
}
builder.Insert(0, temp);
break;
case 1: // Tens column
if (ndigit > 0)
{
temp = String.Format("{0}{1}",
_tens[ndigit],
(digits[i + 1] != '0') ? " si " : " ");
builder.Insert(0, temp);
}
break;
case 2: // Hundreds column
if (ndigit > 0)
{
temp = String.Format("{0} {1} ", ndigit == 1 ? "o" : _ones[ndigit], ndigit == 1 ? "suta" : "sute");
builder.Insert(0, temp);
}
break;
}
}
// You always need "lei" right?
builder.AppendFormat("lei");
// This code simply divides the decimal value by 1; and only adds "si NN bani" if there's a remainder
if (Decimal.Remainder(value, 1) > 0) {
builder.AppendFormat(" si {0:00} bani", (value - (long)value) * 100);
}
// Capitalize first letter
return String.Format("{0}{1}",
Char.ToUpper(builder[0]),
builder.ToString(1, builder.Length - 1));
}
static void Main(string[] args)
{
Console.WriteLine(MakeWordFromNumbers(1127.00M));
Console.WriteLine(MakeWordFromNumbers(2227.00M));
Console.WriteLine(MakeWordFromNumbers(127.00M));
Console.WriteLine(MakeWordFromNumbers(227.00M));
Console.ReadKey();
}
}
}
Upvotes: 2
Reputation: 14334
When preparing an application for localisation (the act of translating and applying translations to an application), you will involve yourself in the process of globalisation.
Globalisation is the process of making our application play nicely with translations. There are a few guidelines to remember.
Upvotes: 0