首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将带小数的数字(货币)转换为单词

将带小数的数字(货币)转换为单词
EN

Stack Overflow用户
提问于 2017-04-11 06:45:05
回答 5查看 11.4K关注 0票数 1

我想将带有小数(货币)的数字转换为word

例: 12345.60 --> 12,345美元60美分

我从http://www.csharp-tutorials.info/2016/04/convert-numbers-to-words-in-c.html得到了这段代码

代码语言:javascript
复制
 public static string NumberToWords(int number)
    {
        if (number == 0)
            return "zero";

        if (number < 0)
            return "minus " + NumberToWords(Math.Abs(number));

        string words = "";

        if ((number / 1000000000) > 0)
        {
            words += NumberToWords(number / 1000000000) + " billion ";
            number %= 1000000000;
        }

        if ((number / 1000000) > 0)
        {
            words += NumberToWords(number / 1000000) + " million ";
            number %= 1000000;
        }

        if ((number / 1000) > 0)
        {
            words += NumberToWords(number / 1000) + " thousand ";
            number %= 1000;
        }

        if ((number / 100) > 0)
        {
            words += NumberToWords(number / 100) + " hundred ";
            number %= 100;
        }

        if (number > 0)
        {
            if (words != "")
                words += " ";

            var unitsMap = new[] { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
            var tensMap = new[] { "zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };

            if (number < 20)
                words += unitsMap[number];
            else
            {
                words += tensMap[number / 10];
                if ((number % 10) > 0)
                    words += "-" + unitsMap[number % 10];
            }
        }

        return words;
    }

它可以很好地处理整数,但如果输入为双精度。它显示错误

因为它只接受int。

我用我的知识尽了最大努力,但我不能改变代码来得到我想要的。

EN

回答 5

Stack Overflow用户

发布于 2017-04-11 08:00:13

问题是你在doubles上使用了模,这(显然)是不允许的。对于浮点之前的部分,必须对给定代码使用Math.Floor(number),对于浮点之后的部分,必须使用number - Math.Floor(number)。其余部分实际上在你的代码示例中给出了,只需在浮点之前的部分之后添加"Dollar",在浮点之后的部分之后添加"cents"。你的代码应该是这样的:

代码语言:javascript
复制
    public static string NumberToWords(double doubleNumber)
    {
        var beforeFloatingPoint = (int) Math.Floor(doubleNumber);
        var beforeFloatingPointWord = $"{NumberToWords(beforeFloatingPoint)} dollars";
        var afterFloatingPointWord =
            $"{SmallNumberToWord((int) ((doubleNumber - beforeFloatingPoint) * 100), "")} cents";
        return $"{beforeFloatingPointWord} and {afterFloatingPointWord}";
    }

    private static string NumberToWords(int number)
    {
        if (number == 0)
            return "zero";

        if (number < 0)
            return "minus " + NumberToWords(Math.Abs(number));

        var words = "";

        if (number / 1000000000 > 0)
        {
            words += NumberToWords(number / 1000000000) + " billion ";
            number %= 1000000000;
        }

        if (number / 1000000 > 0)
        {
            words += NumberToWords(number / 1000000) + " million ";
            number %= 1000000;
        }

        if (number / 1000 > 0)
        {
            words += NumberToWords(number / 1000) + " thousand ";
            number %= 1000;
        }

        if (number / 100 > 0)
        {
            words += NumberToWords(number / 100) + " hundred ";
            number %= 100;
        }

        words = SmallNumberToWord(number, words);

        return words;
    }

    private static string SmallNumberToWord(int number, string words)
    {
        if (number <= 0) return words;
        if (words != "")
            words += " ";

        var unitsMap = new[] { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
        var tensMap = new[] { "zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };

        if (number < 20)
            words += unitsMap[number];
        else
        {
            words += tensMap[number / 10];
            if ((number % 10) > 0)
                words += "-" + unitsMap[number % 10];
        }
        return words;
    }
票数 5
EN

Stack Overflow用户

发布于 2019-02-25 12:47:40

作为上述答案的补充,由于目前大多数系统都是全球化的,因此支持多种货币并支持根据国家识别小数组的不同方式进行转换是很重要的。我通过在json文件中为我想支持的每种关键货币创建模板,然后使用类似于上面的代码(没有硬编码)来从模板中读取数据并进行相应的转换,从而解决了这个问题。模板的例子在下面,让我知道如果有人需要的代码。

将USD转换为words的Json模板

代码语言:javascript
复制
    {
    "currencyKey": "USD",
    "formatMainUnit": "{0} dollar",
    "formatDecimalUnit": "{0} cent",
    "joinMainAndDecimal": "and",
    "ifNoDecimalUnit": "",
    "formatForMinus": "minus {0}",
    "unitsMap": [ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", 
    "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"],
    "tensMap": [ "zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" ],
    "groupMap": [
        {"tenRaiseTo":9, "word":"billion"},
        {"tenRaiseTo":6, "word":"million"},
        {"tenRaiseTo":3, "word":"thousand"},
        {"tenRaiseTo":2, "word":"hundred"}
    ]
}

INR to words的Json模板

代码语言:javascript
复制
{
    "currencyKey": "INR",
    "formatMainUnit": "{0} rupee",
    "formatDecimalUnit": "{0} paisa",
    "joinMainAndDecimal": "and",
    "ifNoDecimalUnit": "zero paisa",
    "formatForMinus": "minus {0}",
    "unitsMap": [ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", 
    "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"],
    "tensMap": [ "zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" ],
    "groupMap": [
        {"tenRaiseTo":7, "word":"crore"},
        {"tenRaiseTo":5, "word":"lak"},
        {"tenRaiseTo":3, "word":"thousand"},
        {"tenRaiseTo":2, "word":"hundred"}
    ]
}

Json模板,用于将泰蓝转换为单词

代码语言:javascript
复制
{
    "currencyKey": "THB",
    "formatMainUnit": "{0} baht",
    "formatDecimalUnit": "{0} satang",
    "joinMainAndDecimal": "and",
    "ifNoDecimalUnit": "No satang",
    "formatForMinus": "minus {0}",
    "unitsMap": [ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", 
    "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"],
    "tensMap": [ "zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" ],
    "groupMap": [
        {"tenRaiseTo":9, "word":"billion"},
        {"tenRaiseTo":6, "word":"million"},
        {"tenRaiseTo":3, "word":"thousand"},
        {"tenRaiseTo":2, "word":"hundred"}
    ]
}

使用上述模板将数字转换为单词的实际C#代码。注意:将自定义框架相关代码替换为您自己的实现(例如: CacheManager)

代码语言:javascript
复制
using System; using System.Collections.Generic; using System.IO;

namespace BF
{
    public class CurrencyToWords
    {
        private CurrencyTemplate template;
        private const string DEFAULT_TEMPLATE = "Default_To_Words";

        public CurrencyToWords(string tplFile)
        {
            if (string.IsNullOrWhiteSpace(tplFile)) tplFile = DEFAULT_TEMPLATE;

            //read the template
            template = LoadTemplate(tplFile);

            if (template == null && tplFile != DEFAULT_TEMPLATE)
            {
                //load default template
                tplFile = DEFAULT_TEMPLATE;

                template = LoadTemplate(tplFile);
            }

            if (template != null)
            {
                //set to cache
                CacheManager.setCacheObject(tplFile, template, 1000);
            }
        }

        private CurrencyTemplate LoadTemplate(string tplFile)
        {
            CurrencyTemplate result = (CurrencyTemplate)CacheManager.getCachedObject(tplFile);

            if (result == null)
            {
                //load from file
                string filePath = CoreConfig.ConstructConfigCurrencyTplPath(tplFile + ".json");

                if (File.Exists(filePath))
                {
                    string jsonMap = System.IO.File.ReadAllText(filePath);
                    result = new CurrencyTemplate();
                    result = (CurrencyTemplate)CommonConversions.DeserializeJSON(jsonMap, result.GetType());
                }
            }

            return result;
        }

        public string ConvertToWords(decimal value)
        {
            if (template == null) return "";

            decimal workingValue = Math.Abs(value);

            decimal beforeFloatingPoint = Math.Floor(workingValue);
            string beforeFloatingPointWord = string.Format(template.formatMainUnit, ConvertParts(beforeFloatingPoint, 0));

            decimal afterFloatingPoint = Math.Floor((workingValue - beforeFloatingPoint) * 100);
            string afterFloatingPointWord;

            if (afterFloatingPoint == 0)
            {
                afterFloatingPointWord = template.ifNoDecimalUnit;
            }
            else
            {
                afterFloatingPointWord = string.Format(template.formatDecimalUnit, ConvertParts(afterFloatingPoint, 0));
            }

            string result;

            if (string.IsNullOrWhiteSpace(afterFloatingPointWord))
            {
                result = beforeFloatingPointWord;
            }
            else
            {
                result = string.Format("{0} {1} {2}", beforeFloatingPointWord, template.joinMainAndDecimal, afterFloatingPointWord);
            }

            //if negative apply template for representing negative value
            if (value < 0)
            {
                result = string.Format(template.formatForMinus, result);
            }

            return result;
        }

        private string ConvertParts(decimal value, int group)
        {
            var words = "";
            CurrencyGroupMap map;
            decimal groupRange;
            decimal workingValue = Math.Floor(value);

            for ( ; group < template.groupMap.Count; group++)
            {
                map = template.groupMap[group];

                groupRange = (decimal) Math.Pow(10, map.tenRaiseTo);

                if (Math.Floor(workingValue / groupRange) > 0)
                {
                    if (words != "")
                        words += ", ";

                    words += string.Format("{0} {1}", ConvertParts(workingValue / groupRange, group + 1), map.word);
                    workingValue %= groupRange;
                }
            }

            words = ConvertSmallNumbers(workingValue, words);

            return words;
        }

        private string ConvertSmallNumbers(decimal value, string words)
        {
            if (value <= 0) return words;

            if (words != "")
                words += " ";

            int index;

            try
            {
                index = (int)value;
            }
            catch
            {
                index = 0;
            }

            if (index < 20)
                words += template.unitsMap[index];
            else
            {
                words += template.tensMap[index / 10];

                if ((index % 10) > 0)
                    words += "-" + template.unitsMap[index % 10];
            }

            return words;
        }
    }

    public class CurrencyTemplate
    {
        public string currencyKey;
        public string formatMainUnit;
        public string formatDecimalUnit;
        public string joinMainAndDecimal;
        public string ifNoDecimalUnit;
        public string formatForMinus;
        public List<string> unitsMap;
        public List<string> tensMap;
        public List<CurrencyGroupMap> groupMap;
    }

    public class CurrencyGroupMap
    {
        public int tenRaiseTo;
        public string word;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2021-04-08 11:42:24

如果目标平台/语言是.NET/C#,那么您可以使用NumericWordsConversion nuget包并根据您的需求进行自定义。示例代码如下:

代码语言:javascript
复制
using NumericWordsConversion;
using System;
using System.Collections.Generic;
using System.Linq;

namespace CurrencyConverterCore
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Currency to words");
            decimal amount = 111100000.12M;

            List<CurrencyFormat> formats = new List<CurrencyFormat>();
            formats.Add(new CurrencyFormat { CurrencyCode = "USD", CurrencyName="United States Dollar", Culture=Culture.International, CurrencyUnit = "", SubCurrencyUnit = "cents" });
            formats.Add(new CurrencyFormat { CurrencyCode = "MYR", CurrencyName="Ringgit Malaysia", Culture = Culture.International, CurrencyUnit = "", SubCurrencyUnit = "cents" });
            formats.Add(new CurrencyFormat { CurrencyCode = "SGD", CurrencyName = "Singapore Dollar", Culture = Culture.International, CurrencyUnit = "", SubCurrencyUnit = "cents" });
            formats.Add(new CurrencyFormat { CurrencyCode = "INR", CurrencyName = "Indian Rupee", Culture = Culture.Hindi, CurrencyUnit = "rupee", SubCurrencyUnit = "paisa" });
            formats.Add(new CurrencyFormat { CurrencyCode = "THB", CurrencyName = "Thai Baht", Culture = Culture.International, CurrencyUnit = "", SubCurrencyUnit = "satang" });
            formats.Add(new CurrencyFormat { CurrencyCode = "BDT", CurrencyName = "Bangladesh Taka", Culture = Culture.Hindi, CurrencyUnit = "taka", SubCurrencyUnit = "paisa" });

            CurrencyWordsConverter converter = null;

            string currencyToConvert = "BDT";
            string words = "";
            var format = formats.Where(x => x.CurrencyCode == currencyToConvert).FirstOrDefault();

            if (format != null)
            {
                
                converter = new CurrencyWordsConverter(new CurrencyWordsConversionOptions()
                {
                    Culture = format.Culture,
                    OutputFormat = OutputFormat.English,
                    CurrencyUnitSeparator = "and",
                    CurrencyUnit = format.CurrencyUnit,
                    SubCurrencyUnit = format.SubCurrencyUnit,
                    EndOfWordsMarker = "only"
                });

                words = (format.CurrencyUnit == "" ? (format.CurrencyName + " ") : "") + converter.ToWords(amount);
            }
            else
            {
                converter = new CurrencyWordsConverter();
                words = converter.ToWords(amount);
            }


            

            Console.WriteLine(words);
            Console.ReadKey();

        }

        class CurrencyFormat
        {
            public string CurrencyCode { get; set; }
            public string CurrencyName { get; set; }
            public Culture Culture { get; set; }
            public string CurrencyUnit { get; set; }
            public string SubCurrencyUnit { get; set; }

        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43334034

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档