function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
SabrentSabrent 

Math Function

can someone please explain to me how this code is conerting String to word. I would apprecite you rhelp.Thanks

 

//Takes a Number as a String, and makes it into the word number.
public String toWords(String s){
    String[] th = new String[]{'','thousand','million', 'billion','trillion'};
    String[] dg = new String[]{'zero','one','two','three','four', 'five','six','seven','eight','nine'};
    String[] tn = new String[]{'ten','eleven','twelve','thirteen', 'fourteen','fifteen','sixteen', 'seventeen','eighteen','nineteen'};
    String[] tw = new String[]{'twenty','thirty','forty','fifty', 'sixty','seventy','eighty','ninety'};
   
    s = s.replace(',','');
        Integer x = 0;
        x = s.indexOf('.');
        if (x == -1) x = s.length();
        if (x > 15) return 'too big';
        String[] qr = s.split('');
        Integer[] n = new Integer[0];
        for (Integer i=1;i < qr.size();i++){
            n.add(Integer.valueOf(qr[i]));
        }
        String str = '';
        Integer sk = 0;
        for (Integer i=0; i < x; i++) {
            if (math.mod(x-i,3)==2){
                if (n[i] == 1) {
                    str += tn[n[i+1]] + ' ';
                    i++; sk=1;
                }
                else if (n[i]!=0) {
                    str += tw[n[i]-2] + ' ';
                    sk=1;
                }
            }
            else if (n[i]!=0) {
                str += dg[n[i]] +' ';
                if(math.mod(x-i,3)==0) str += 'hundred ';
                sk=1;
            }
            if(math.mod(x-i,3)==1){
                if (sk==1) str += th[(x-i-1)/3] + ' ';
                sk=0;
            }
        }
        if (x != s.length()) {
            Integer y = s.length();
            str += 'point ';
            for (Integer i=x+1; i<y; i++) str += dg[n[i]] +' ';
        }
        return str;
       
}

 




mulvelingmulveling

Yeah, that's a bit tough to read -- but still nothing compared to the massively insane logic some of the Scientific Computing folks write.

 

Unfortunately, what constitutes good optimization on traditional platforms can be extremely counter-productive in Apex, since the REAL bottleneck here is # of script statements -- and sometimes, stack depth -- and rarely, heap size.

 

Here's my first rough stab at a slightly more human-readable Apex version of "number wordify" -- clearly it can be refined, optimized, and cleaned up further:

 

public class Options {
    public String hundred = ' hundred';
    public String zero = 'zero';
    public String andJoin = ' and ';
    public String plainJoin = ' ';
    public String hyphenJoin = '-';
    public String intDecJoin = ', ';
    public String[] ones = 'zero one two three four five six seven eight nine ten'.split(' ');
    public String[] teens = ('ten eleven twelve thirteen fouteen fifteen sixteen seventeen ' + 
            'eighteen nineteen').split(' ');
    public String[] tens = '  twenty thirty fourty fifty sixty seventy eighty ninety'.split(' ');
    public String[] qualifiers = ('thousand million billion trillion quadrillion quintillion ' + 
            'sextillion septillion octillion nonillion decillion undecillion duodecillion ' + 
            'tredecillion quattuordecillion quindecillion sexdecillion septendecillion ' + 
            'octodecillion novemdecillion vigintillion').split(' ');
    public String qualifierJoin = ', ';
    public String point = 'point';
    public String pointJoin = plainJoin + point;
}
public String[] chars(String str) {
    String[] chars = str.split('');
    if (chars.size() > 0) {
        chars.remove(0);
    }
    return chars;
}
public class FormatException extends Exception {}
public static String wordifyDecimal(String strNumber) {
    return wordifyDecimal(new Options(), strNumber);
}
public static String wordifyDecimal(Options opts, String strNumber) {
    Integer decimalIndex = strNumber.indexOf('.');
    if (decimalIndex >= 0) {
        String decimalWords = '';
        // strip trailing zeros from the decimal component:
        String strDecimal = strNumber.substring(decimalIndex + 1, strNumber.length()).
                replaceAll('([^0])[0]+$', '$1');
        for (Integer i=0; i < strDecimal.length(); i++) {
            decimalWords += (i > 0 ? opts.hyphenJoin : '') + 
                    opts.ones[Integer.valueOf(strDecimal.substring(i, i+1))]; 
        }
        return wordifyInt(opts, strNumber.substring(0, decimalIndex)) + 
                (decimalIndex > 0 ? opts.pointJoin : opts.point) + opts.plainJoin + 
                    decimalWords;
    }
    return wordifyInt(new Options(), strNumber);
}

public static String wordifyInt(String strInt) {
    return wordifyInt(new Options(), strInt);
}
public static String wordifyInt(Options opts, String strInt) {
    strInt = strInt == null ? '' : strInt.replaceAll('\\s', '');
    if (strInt == '') {
        return strInt;
    }
    // ensure we've got a valid int:
    if (!Pattern.compile('\\d+').matcher(strInt).matches()) {
        throw new FormatException('Invalid integer: ' + strInt);
    }
    // reduce leading zeros:
    strInt = strInt.replaceAll('^[0]+', '');
    if (strInt == '') {
        return opts.zero;
    }
    // break the integer up into millenial chunks of 3 digits, starting from the 
    // least-significant (i.e. right-most) digit:
    String buffer = '';
    Integer qualifierIndex = -1;
    for (Integer i=strInt.length() - 3; i >= -2; i -= 3) {
        if (qualifierIndex >= opts.qualifiers.size()) {
            throw new FormatException('Integer is too long');
        }
        // left-pad-0 as necessary, if we're on our most significant chunk:
        String[] chars = chars((i == -2 ? '00' : (i == -1 ? '0' : '')) + 
                strInt.substring(Math.max(0, i), i + 3));
        String chunk = wordifyMillenia(opts, new Integer[]{
            Integer.valueOf(chars[0]), Integer.valueOf(chars[1]), Integer.valueOf(chars[2])});
        buffer = chunk + (qualifierIndex >= 0 ? opts.plainJoin + opts.qualifiers[qualifierIndex] + 
                opts.qualifierJoin : '') + buffer;
        qualifierIndex++;
    }
    return buffer;
}
// takes in 3 digits representing a "millenia", with index 0 being the most significant 
// digits (i.e. hundreds) and first breaks it down into an array of 3 string 'bits', some 
// or all of which may be null -- e.g. 805 => {'eight', null, 'five'}, 034 => 
// {null, 'thirty', 'four'}, 217 => {'two', 'seventeen', null} -- and then joins those bits according 
// to options. 
public static String wordifyMillenia(Options opts, Integer[] digits) {
    String[] bits = new String[]{null, null, null};
    // hundreds column:
    if (digits[0] > 0) {
        bits[0] = opts.ones[digits[0]];
    }
    // tens column:
    if (digits[1] == 1) {
        // 1 in the decades column -- e.g. eleven, sixteen:
        bits[1] = opts.teens[digits[2]];
        return joinBits(opts, bits);
    } else if (digits[1] > 1) {
        bits[1] = opts.tens[digits[1]];
    }
    // ones column:
    if (digits[2] > 0) {
        bits[2] = opts.ones[digits[2]];
    }
    return joinBits(opts, bits);
}
public static String joinBits(Options opts, String[] bits) {
    String buffer = '';
    if (bits[0] != null) {
        buffer += bits[0] + opts.hundred;
    }
    if (bits[1] != null) {
        buffer += (bits[0] != null ? opts.andJoin : '') + bits[1] + 
                (bits[2] != null ? opts.hyphenJoin + bits[2] : '');
    } else if (bits[2] != null) {
        buffer += (bits[0] != null ? opts.andJoin : '') + bits[2];
    }
    return buffer;
}

System.debug(wordifyDecimal('0078645100514708413.1400'));
System.debug(wordifyDecimal('00.098334'));
System.debug(wordifyDecimal('1234'));
System.debug(wordifyDecimal('3.14'));
System.debug(wordifyDecimal('603'));

 -- 

Mike

SabrentSabrent

Steve, Thanks for the elaborate explanation. Though i am still trying to understand, it is indeed more readable.

mulvelingmulveling

The name is Mike :)

Feel free to ask about the details of a specific piece.