HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Int2Word

01-23-2010, 10:08 AM#1
Ammorth
Int2Word.

Converts an integer into a string of English numbers. It can handle any value possible.

Collapse JASS:
// ============================================================================
// Int2Word - By Ammorth                                         Jan 29, 2009
//   **Requires JassHelper (vJass) to compile**        
//   Thanks to Grim001 for the improved version (less comparisons).
//
// use Int2Word(integer) to get a string of the integer passed.
// Can handle any signed 32 bit number (what wc3 uses), including negatives.
//
// User Function:
//     function Int2Word takes integer i returns string
//
// set message = Int2Word(8342)
// call BJDebugMsg(message) // displays "eight thousand three hundred forty-two"
//
// set message = Int2Word(-10000)
// call BJDebugMsg(message) // displays "negative ten thousand"
//
// =============================================================================
library Int2Word initializer onInit

    globals
        private string array zero
        private string array space
        private string array basic // stores the basic values
        private string array dashbasic // stores the basic values with dashes
        private string array tens // stores the tens
        private constant string hundred = " hundred" // needs leading space for formatting
        private constant string thousand = " thousand" // needs leading space for formatting
        private constant string million = " million" // needs leading space for formatting
        private constant string billion = " billion" // needs leading space for formatting
        private constant string negative = "negative " // needs trailing space for formatting
        private constant integer Zero = 0
        private constant integer NoZero = 1
        private constant integer Space = 0
        private constant integer NoSpace = 1
    endglobals
    
    function Int2Word_Sub takes integer i, integer z, integer s returns string
            if i == 0 then
                return zero[z] //returns null string if Zero != 0
            elseif i < 0 then // add negative to the front and get the words for the positive value
                return negative+Int2Word_Sub(-i, NoZero, NoSpace)
            elseif i < 20 then // we can handle these with a simple array lookup
                return space[s]+basic[i]
            elseif i < 100 then // under 100
                return space[s]+tens[i / 10]+dashbasic[i - (i / 10)*10] 
            elseif i < 1000 then // under 1000
                return space[s]+basic[i / 100]+hundred+Int2Word_Sub(i - (i / 100)*100, NoZero, Space)
            elseif i < 1000000 then // under a million
                return space[s]+Int2Word_Sub(i / 1000, NoZero, NoSpace)+thousand+Int2Word_Sub(i - (i / 1000)*1000, NoZero, Space)
            elseif i < 1000000000 then // under a billion
                return space[s]+Int2Word_Sub(i / 1000000, NoZero, NoSpace)+million+Int2Word_Sub(i - (i / 1000000)*1000000, NoZero, Space)
            endif // a billion and up...
        return space[s]+basic[i/1000000000]+billion+Int2Word_Sub(i - (i / 1000000000)*1000000000, NoZero, Space)
    endfunction
    
    function Int2Word takes integer i returns string
        return Int2Word_Sub(i, Zero, NoSpace)
    endfunction
    
    private function onInit takes nothing returns nothing
        set zero[0] = "zero"
        set space[0] = " "
        set basic[0] = "" // the basic numbers
        set basic[1] = "one"
        set basic[2] = "two"
        set basic[3] = "three"
        set basic[4] = "four"
        set basic[5] = "five"
        set basic[6] = "six"
        set basic[7] = "seven"
        set basic[8] = "eight"
        set basic[9] = "nine"
        set basic[10] = "ten"    // isn't included in tens, since the teens have some oddities
        set basic[11] = "eleven" // that require them to be in the basic section (damn english)
        set basic[12] = "twelve"
        set basic[13] = "thirteen"
        set basic[14] = "fourteen"
        set basic[15] = "fifteen"
        set basic[16] = "sixteen"
        set basic[17] = "seventeen"
        set basic[18] = "eighteen"
        set basic[19] = "nineteen"
        set dashbasic[0] = ""
        set dashbasic[1] = "-one"
        set dashbasic[2] = "-two"
        set dashbasic[3] = "-three"
        set dashbasic[4] = "-four"
        set dashbasic[5] = "-five"
        set dashbasic[6] = "-six"
        set dashbasic[7] = "-seven"
        set dashbasic[8] = "-eight"
        set dashbasic[9] = "-nine"
        set tens[2] = "twenty" // now we can count by tens
        set tens[3] = "thirty"
        set tens[4] = "forty"
        set tens[5] = "fifty"
        set tens[6] = "sixty"
        set tens[7] = "seventy"
        set tens[8] = "eighty"
        set tens[9] = "ninety"
    endfunction
endlibrary

I have tested this quickly, so all the 10...00 should have the right number of zeros. Please speak up if I missed something.

If you want to capitalize the first letter, you can use a wrapper (example posted here) or a string library that can do it for you.

I have seen azlier's GetIntName and this is supposed to be the rest of the number set Rising_Dusk was asking for (although I couldn't stop at just 10000).
01-23-2010, 05:49 PM#2
TriggerHappy
This was brought up in the other thread, iirc.
Why the hell would you need to go past the hundreds?

In what sane scenario would you type these large numbers?
01-23-2010, 06:07 PM#3
TEC_Ghost
This is nifty as fuck, good job!
01-23-2010, 07:00 PM#4
Ammorth
Quote:
Originally Posted by TriggerHappy
This was brought up in the other thread, iirc.
Why the hell would you need to go past the hundreds?

In what sane scenario would you type these large numbers?

Well, I could see reasons to go up to hundred thousands (quest rewards for exp/gold late-game) and then larger numbers (expecially those with many zeros) are easier to read if spelled out 100000000 vs one hundred million.

Of course, it makes no sense to only include the numbers that are powers of 10 only for larger number, especially since the solution is simple with recursion.
01-24-2010, 02:48 PM#5
Iron_Doors
Quote:
Originally Posted by TriggerHappy
This was brought up in the other thread, iirc.
Why the hell would you need to go past the hundreds?

In what sane scenario would you type these large numbers?

Freedom comes practically free in this case. If you ask me, you'd need a good reason to not want this, instead of the other way around.
01-24-2010, 03:55 PM#6
Rising_Dusk
I'd use the function name I2Word.
01-24-2010, 08:06 PM#7
Ammorth
Quote:
Originally Posted by Rising_Dusk
I'd use the function name I2Word.

Originally I had it Integer2Word and thought I should change it to Int2Word. Personally, I think I2Word is far worse than Int2Word, since it doesn't match any conventions. I2W would be much better, if that were the case.
01-24-2010, 08:19 PM#8
Hans_Maulwurf
Quote:
// isn't included in tens, since the teens have some oddities
// that require them to be in the basic section (damn english)

could be worse. eg 99 in french is "quatre-vingt-dix-neuf" aka 4 times twenty plus ten plus nine.
01-25-2010, 02:34 AM#9
weaaddar
You should consider switching to a binary approach for figuring out the logarithmic scale instead of linear.
01-25-2010, 02:50 AM#10
grim001
I think it's going to be extremely more frequent that small-ish values are converted, so the linear approach will outperform the bineary search in most situations. Although readability outweighs performance for this kind of function.
01-25-2010, 09:17 AM#11
Ammorth
Quote:
Originally Posted by grim001
I think it's going to be extremely more frequent that small-ish values are converted, so the linear approach will outperform the bineary search in most situations. Although readability outweighs performance for this kind of function.

I'm slightly confused what you meant by the last sentence. My approach and code orginization is good or that going to binary would be an improvement to readability?

Also, have we decided about I2W or I2Word? I personally like I2W, but if someone provides an argument against it, I would gladly listen.
01-25-2010, 09:44 AM#12
akolyt0r
i think I2W would be inappropriate ... all the X2X functions are for type conversions, and should be reserverd for type conversions, and a "(english) written number" is not even a type..

I would like Int2WrittenForm, maybe even Int2EnglishWrittenForm... but thats maybe just me... but you really should not use I2W.
01-25-2010, 10:49 AM#13
Anachron
Maybe Int2Word.
01-25-2010, 04:05 PM#14
syltman
Quote:
Originally Posted by akolyt0r
i think I2W would be inappropriate ... all the X2X functions are for type conversions, and should be reserverd for type conversions, and a "(english) written number" is not even a type..

I would like Int2WrittenForm, maybe even Int2EnglishWrittenForm... but thats maybe just me... but you really should not use I2W.

Int2EnglishWrittenForm is waaaay to long to type. And wouldn't Integer to word be a type convertion? It's the same thing as I2S.

I think that I2Word would be best.
01-25-2010, 04:30 PM#15
grim001
Quote:
Originally Posted by Ammorth
I'm slightly confused what you meant by the last sentence. My approach and code orginization is good or that going to binary would be an improvement to readability?
Binary search would probably just make it harder to read. I just mean that performance means little for this kind of function.