Converting numbers into English
-
So I've been enjoying myself at work today: I wrote something to take a number and convert it into English, e.g. "12324.56" becomes "twelve thousand, three hundred and twenty-four point five six". I know this is an old problem: I remember having done this something like 30 years ago, as part of a computer science class, but I actually needed it for something today: in doing it, I was amazed at how many ways there are to achieve it in C# (the last time I wrote it, it was in Algol-60!), and how many little optimizations I was able to add as I sat there looking at each iteration of the code. I ended up trying to keep the code as terse as I could but also as fast as I could, without having too many IFs and things all over the place. I ended up using a bunch of enums and letting the runtime make words out of them, rather than having strings for it: I'm not sure it makes a huge difference, but it just seemed more elegant, somehow. Of course, in a problem like this, there's always the part about trying to stop it saying things like, "two thousand, zero hundred and onety-zero", so part of the fun was trying not to write anything too specific to avoid things like that: in my mind, if I got the algorithm right, that stuff would just sort of work... It's nice having a bit of time on one's hands at work, for a change. Anyway, I had a lot of fun, so I thought I'd share: if anyone else has a better method (and I'm sure they do) then why not join in...? Meanwhile, here's my version:
public static class Numeric
{
private enum Digit
{
zero = 0, one = 1, two = 2, three = 3, four = 4,
five = 5, six = 6, seven = 7, eight = 8, nine = 9
}private enum Teen
{
ten = 10, eleven = 11, twelve = 12, thirteen = 13, fourteen = 14,
fifteen = 15, sixteen = 16, seventeen = 17, eighteen = 18, nineteen = 19
}private enum Ten
{
twenty = 2, thirty = 3, forty = 4, fifty = 5,
sixty = 6, seventy = 7, eighty = 8, ninety = 9
}private enum PowerOfTen
{
hundred = 0, thousand = 1, million = 2, billion = 3,
trillion = 4, quadrillion = 5, quintillion = 6
}/// /// How many powers of ten there are; faster to work this out ahead of time,
/// and I didn't want to hard-code it into the algorithm...
///
private static int PowersOfTen = Enum.GetValues(typeof(PowerOfTen)).Length;/// /// Converts a number to English words
///
/// The number -
So I've been enjoying myself at work today: I wrote something to take a number and convert it into English, e.g. "12324.56" becomes "twelve thousand, three hundred and twenty-four point five six". I know this is an old problem: I remember having done this something like 30 years ago, as part of a computer science class, but I actually needed it for something today: in doing it, I was amazed at how many ways there are to achieve it in C# (the last time I wrote it, it was in Algol-60!), and how many little optimizations I was able to add as I sat there looking at each iteration of the code. I ended up trying to keep the code as terse as I could but also as fast as I could, without having too many IFs and things all over the place. I ended up using a bunch of enums and letting the runtime make words out of them, rather than having strings for it: I'm not sure it makes a huge difference, but it just seemed more elegant, somehow. Of course, in a problem like this, there's always the part about trying to stop it saying things like, "two thousand, zero hundred and onety-zero", so part of the fun was trying not to write anything too specific to avoid things like that: in my mind, if I got the algorithm right, that stuff would just sort of work... It's nice having a bit of time on one's hands at work, for a change. Anyway, I had a lot of fun, so I thought I'd share: if anyone else has a better method (and I'm sure they do) then why not join in...? Meanwhile, here's my version:
public static class Numeric
{
private enum Digit
{
zero = 0, one = 1, two = 2, three = 3, four = 4,
five = 5, six = 6, seven = 7, eight = 8, nine = 9
}private enum Teen
{
ten = 10, eleven = 11, twelve = 12, thirteen = 13, fourteen = 14,
fifteen = 15, sixteen = 16, seventeen = 17, eighteen = 18, nineteen = 19
}private enum Ten
{
twenty = 2, thirty = 3, forty = 4, fifty = 5,
sixty = 6, seventy = 7, eighty = 8, ninety = 9
}private enum PowerOfTen
{
hundred = 0, thousand = 1, million = 2, billion = 3,
trillion = 4, quadrillion = 5, quintillion = 6
}/// /// How many powers of ten there are; faster to work this out ahead of time,
/// and I didn't want to hard-code it into the algorithm...
///
private static int PowersOfTen = Enum.GetValues(typeof(PowerOfTen)).Length;/// /// Converts a number to English words
///
/// The numberProbably would have been better posting this as a Tip/Trick rather than in the Lounge...
Quad skating his way through the world since the early 80's... Booger Mobile - My bright green 1964 Ford Falcon - check out the blog here!! | If you feel generous - make a donation to Camp Quality!!
-
So I've been enjoying myself at work today: I wrote something to take a number and convert it into English, e.g. "12324.56" becomes "twelve thousand, three hundred and twenty-four point five six". I know this is an old problem: I remember having done this something like 30 years ago, as part of a computer science class, but I actually needed it for something today: in doing it, I was amazed at how many ways there are to achieve it in C# (the last time I wrote it, it was in Algol-60!), and how many little optimizations I was able to add as I sat there looking at each iteration of the code. I ended up trying to keep the code as terse as I could but also as fast as I could, without having too many IFs and things all over the place. I ended up using a bunch of enums and letting the runtime make words out of them, rather than having strings for it: I'm not sure it makes a huge difference, but it just seemed more elegant, somehow. Of course, in a problem like this, there's always the part about trying to stop it saying things like, "two thousand, zero hundred and onety-zero", so part of the fun was trying not to write anything too specific to avoid things like that: in my mind, if I got the algorithm right, that stuff would just sort of work... It's nice having a bit of time on one's hands at work, for a change. Anyway, I had a lot of fun, so I thought I'd share: if anyone else has a better method (and I'm sure they do) then why not join in...? Meanwhile, here's my version:
public static class Numeric
{
private enum Digit
{
zero = 0, one = 1, two = 2, three = 3, four = 4,
five = 5, six = 6, seven = 7, eight = 8, nine = 9
}private enum Teen
{
ten = 10, eleven = 11, twelve = 12, thirteen = 13, fourteen = 14,
fifteen = 15, sixteen = 16, seventeen = 17, eighteen = 18, nineteen = 19
}private enum Ten
{
twenty = 2, thirty = 3, forty = 4, fifty = 5,
sixty = 6, seventy = 7, eighty = 8, ninety = 9
}private enum PowerOfTen
{
hundred = 0, thousand = 1, million = 2, billion = 3,
trillion = 4, quadrillion = 5, quintillion = 6
}/// /// How many powers of ten there are; faster to work this out ahead of time,
/// and I didn't want to hard-code it into the algorithm...
///
private static int PowersOfTen = Enum.GetValues(typeof(PowerOfTen)).Length;/// /// Converts a number to English words
///
/// The numberYes, a few of these (though not in English) usually show up about this time each year as first-year students post their first quarter accomplishments. Why not one big enum? Don't use Convert! :mad: You don't support milliard. :-D
-
Yes, a few of these (though not in English) usually show up about this time each year as first-year students post their first quarter accomplishments. Why not one big enum? Don't use Convert! :mad: You don't support milliard. :-D
Really? Convert's slow? Thanks!
-
Yes, a few of these (though not in English) usually show up about this time each year as first-year students post their first quarter accomplishments. Why not one big enum? Don't use Convert! :mad: You don't support milliard. :-D
I didn't do one big enum because it's kind of a hack: if you look at the numbers I've made the things equal, it sort of corresponds to the values of my variables, so there's less screwing around to do: for example, the powers of ten thing is really the value of the iterator in the loop that's running through them...
-
Probably would have been better posting this as a Tip/Trick rather than in the Lounge...
Quad skating his way through the world since the early 80's... Booger Mobile - My bright green 1964 Ford Falcon - check out the blog here!! | If you feel generous - make a donation to Camp Quality!!
Ah - OK!
-
So I've been enjoying myself at work today: I wrote something to take a number and convert it into English, e.g. "12324.56" becomes "twelve thousand, three hundred and twenty-four point five six". I know this is an old problem: I remember having done this something like 30 years ago, as part of a computer science class, but I actually needed it for something today: in doing it, I was amazed at how many ways there are to achieve it in C# (the last time I wrote it, it was in Algol-60!), and how many little optimizations I was able to add as I sat there looking at each iteration of the code. I ended up trying to keep the code as terse as I could but also as fast as I could, without having too many IFs and things all over the place. I ended up using a bunch of enums and letting the runtime make words out of them, rather than having strings for it: I'm not sure it makes a huge difference, but it just seemed more elegant, somehow. Of course, in a problem like this, there's always the part about trying to stop it saying things like, "two thousand, zero hundred and onety-zero", so part of the fun was trying not to write anything too specific to avoid things like that: in my mind, if I got the algorithm right, that stuff would just sort of work... It's nice having a bit of time on one's hands at work, for a change. Anyway, I had a lot of fun, so I thought I'd share: if anyone else has a better method (and I'm sure they do) then why not join in...? Meanwhile, here's my version:
public static class Numeric
{
private enum Digit
{
zero = 0, one = 1, two = 2, three = 3, four = 4,
five = 5, six = 6, seven = 7, eight = 8, nine = 9
}private enum Teen
{
ten = 10, eleven = 11, twelve = 12, thirteen = 13, fourteen = 14,
fifteen = 15, sixteen = 16, seventeen = 17, eighteen = 18, nineteen = 19
}private enum Ten
{
twenty = 2, thirty = 3, forty = 4, fifty = 5,
sixty = 6, seventy = 7, eighty = 8, ninety = 9
}private enum PowerOfTen
{
hundred = 0, thousand = 1, million = 2, billion = 3,
trillion = 4, quadrillion = 5, quintillion = 6
}/// /// How many powers of ten there are; faster to work this out ahead of time,
/// and I didn't want to hard-code it into the algorithm...
///
private static int PowersOfTen = Enum.GetValues(typeof(PowerOfTen)).Length;/// /// Converts a number to English words
///
/// The numberWhat I would ask myself is: Why did you re-invent the wheel? Was this good value for money for your employer? There are many many solutions available to do this (for free) on the interwebs. Why did it need to be 'terse and fast' - surely better to be 'easily readable, debuggable and maintainable'?
MVVM # - I did it My Way ___________________________________________ Man, you're a god. - walterhevedeich 26/05/2011 .\\axxx (That's an 'M')
-
Really? Convert's slow? Thanks!
Needless really, it just wraps the Parse routines you should be using. Extra calls on the stack. Shows lack of clarity of thought.
-
What I would ask myself is: Why did you re-invent the wheel? Was this good value for money for your employer? There are many many solutions available to do this (for free) on the interwebs. Why did it need to be 'terse and fast' - surely better to be 'easily readable, debuggable and maintainable'?
MVVM # - I did it My Way ___________________________________________ Man, you're a god. - walterhevedeich 26/05/2011 .\\axxx (That's an 'M')
Curmudgeon
"If you think it's expensive to hire a professional to do the job, wait until you hire an amateur." Red Adair. Those who seek perfection will only find imperfection nils illegitimus carborundum me, me, me me, in pictures
-
Curmudgeon
"If you think it's expensive to hire a professional to do the job, wait until you hire an amateur." Red Adair. Those who seek perfection will only find imperfection nils illegitimus carborundum me, me, me me, in pictures
mark merrens wrote:
Curmudgeonprofessional
ftfy
MVVM # - I did it My Way ___________________________________________ Man, you're a god. - walterhevedeich 26/05/2011 .\\axxx (That's an 'M')
-
Needless really, it just wraps the Parse routines you should be using. Extra calls on the stack. Shows lack of clarity of thought.
PIEBALDconsult wrote:
Shows lack of clarity of thought
Or simple ignorance.
The difficult we do right away... ...the impossible takes slightly longer.
-
So I've been enjoying myself at work today: I wrote something to take a number and convert it into English, e.g. "12324.56" becomes "twelve thousand, three hundred and twenty-four point five six". I know this is an old problem: I remember having done this something like 30 years ago, as part of a computer science class, but I actually needed it for something today: in doing it, I was amazed at how many ways there are to achieve it in C# (the last time I wrote it, it was in Algol-60!), and how many little optimizations I was able to add as I sat there looking at each iteration of the code. I ended up trying to keep the code as terse as I could but also as fast as I could, without having too many IFs and things all over the place. I ended up using a bunch of enums and letting the runtime make words out of them, rather than having strings for it: I'm not sure it makes a huge difference, but it just seemed more elegant, somehow. Of course, in a problem like this, there's always the part about trying to stop it saying things like, "two thousand, zero hundred and onety-zero", so part of the fun was trying not to write anything too specific to avoid things like that: in my mind, if I got the algorithm right, that stuff would just sort of work... It's nice having a bit of time on one's hands at work, for a change. Anyway, I had a lot of fun, so I thought I'd share: if anyone else has a better method (and I'm sure they do) then why not join in...? Meanwhile, here's my version:
public static class Numeric
{
private enum Digit
{
zero = 0, one = 1, two = 2, three = 3, four = 4,
five = 5, six = 6, seven = 7, eight = 8, nine = 9
}private enum Teen
{
ten = 10, eleven = 11, twelve = 12, thirteen = 13, fourteen = 14,
fifteen = 15, sixteen = 16, seventeen = 17, eighteen = 18, nineteen = 19
}private enum Ten
{
twenty = 2, thirty = 3, forty = 4, fifty = 5,
sixty = 6, seventy = 7, eighty = 8, ninety = 9
}private enum PowerOfTen
{
hundred = 0, thousand = 1, million = 2, billion = 3,
trillion = 4, quadrillion = 5, quintillion = 6
}/// /// How many powers of ten there are; faster to work this out ahead of time,
/// and I didn't want to hard-code it into the algorithm...
///
private static int PowersOfTen = Enum.GetValues(typeof(PowerOfTen)).Length;/// /// Converts a number to English words
///
/// The number -
What I would ask myself is: Why did you re-invent the wheel? Was this good value for money for your employer? There are many many solutions available to do this (for free) on the interwebs. Why did it need to be 'terse and fast' - surely better to be 'easily readable, debuggable and maintainable'?
MVVM # - I did it My Way ___________________________________________ Man, you're a god. - walterhevedeich 26/05/2011 .\\axxx (That's an 'M')
Because I felt like it. And I am my employer, so it was excellent value!
-
PIEBALDconsult wrote:
Shows lack of clarity of thought
Or simple ignorance.
The difficult we do right away... ...the impossible takes slightly longer.
Or casting pearls before swine.
-
Or casting pearls before swine.
:confused:
The difficult we do right away... ...the impossible takes slightly longer.
-
PIEBALDconsult wrote:
Shows lack of clarity of thought
Or simple ignorance.
The difficult we do right away... ...the impossible takes slightly longer.
If he were doing VB I'd agree.
-
Because I felt like it. And I am my employer, so it was excellent value!
As a purely fun exercise it's the kind of thing I enjoy doing; I don't think it was good financial value regardless as to who the employer was - although keeping the staff happy is equally important ;)
MVVM # - I did it My Way ___________________________________________ Man, you're a god. - walterhevedeich 26/05/2011 .\\axxx (That's an 'M')
-
So I've been enjoying myself at work today: I wrote something to take a number and convert it into English, e.g. "12324.56" becomes "twelve thousand, three hundred and twenty-four point five six". I know this is an old problem: I remember having done this something like 30 years ago, as part of a computer science class, but I actually needed it for something today: in doing it, I was amazed at how many ways there are to achieve it in C# (the last time I wrote it, it was in Algol-60!), and how many little optimizations I was able to add as I sat there looking at each iteration of the code. I ended up trying to keep the code as terse as I could but also as fast as I could, without having too many IFs and things all over the place. I ended up using a bunch of enums and letting the runtime make words out of them, rather than having strings for it: I'm not sure it makes a huge difference, but it just seemed more elegant, somehow. Of course, in a problem like this, there's always the part about trying to stop it saying things like, "two thousand, zero hundred and onety-zero", so part of the fun was trying not to write anything too specific to avoid things like that: in my mind, if I got the algorithm right, that stuff would just sort of work... It's nice having a bit of time on one's hands at work, for a change. Anyway, I had a lot of fun, so I thought I'd share: if anyone else has a better method (and I'm sure they do) then why not join in...? Meanwhile, here's my version:
public static class Numeric
{
private enum Digit
{
zero = 0, one = 1, two = 2, three = 3, four = 4,
five = 5, six = 6, seven = 7, eight = 8, nine = 9
}private enum Teen
{
ten = 10, eleven = 11, twelve = 12, thirteen = 13, fourteen = 14,
fifteen = 15, sixteen = 16, seventeen = 17, eighteen = 18, nineteen = 19
}private enum Ten
{
twenty = 2, thirty = 3, forty = 4, fifty = 5,
sixty = 6, seventy = 7, eighty = 8, ninety = 9
}private enum PowerOfTen
{
hundred = 0, thousand = 1, million = 2, billion = 3,
trillion = 4, quadrillion = 5, quintillion = 6
}/// /// How many powers of ten there are; faster to work this out ahead of time,
/// and I didn't want to hard-code it into the algorithm...
///
private static int PowersOfTen = Enum.GetValues(typeof(PowerOfTen)).Length;/// /// Converts a number to English words
///
/// The numberP.S. Maybe look into using a StringBuilder It's too early for a Friday Programming Quiz.
-
As a purely fun exercise it's the kind of thing I enjoy doing; I don't think it was good financial value regardless as to who the employer was - although keeping the staff happy is equally important ;)
MVVM # - I did it My Way ___________________________________________ Man, you're a god. - walterhevedeich 26/05/2011 .\\axxx (That's an 'M')
Oh, yeah - I wouldn't bother unless I had a slow day: in this case, I did - it was purely for fun.
-
Needless really, it just wraps the Parse routines you should be using. Extra calls on the stack. Shows lack of clarity of thought.
A parser isn't really applicable here: you can't exactly parse a string of digits into English...