JavaScript Arabic and Chinese numerals convert to each other

One time in the front-end communication group in Shanghai, I saw someone send a help message to the group:

Write a function in JavaScript that requires the entry parameter to be a number. The range of values is an integer number and the return value is a string. The function of the function is to return the Chinese characters corresponding to the number, for example, to enter the number 6, to return the Chinese character "six"; to enter the number 9, to return the Chinese character "nine".

Then I immediately lost an angular filter code I wrote previously that translated into Chinese numerals

  //-Convert lowercase numbers to uppercase, only to [0 ~ 99]
  function numberConvertToUppercase() {
    return function(num) {
      num = Number(num);
      var upperCaseNumber = ['Fatal Frame', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'hundred', 'thousand', 'ten thousand', 'Billions'];
      var length = String(num).length;
      if (length == 1) {
        return upperCaseNumber[num];
      } else if (length == 2) {
        if (num == 10) {
          return upperCaseNumber[num];
        } else if (num > 10 && num < 20) {
          return 'ten' + upperCaseNumber[String(num).charAt(1)];
        } else {
          return upperCaseNumber[String(num).charAt(0)] + 'ten' + upperCaseNumber[String(num).charAt(1)].replace('Fatal Frame', '');
        }
      }
    }
  }

Then there was a response:

  • wolf, you're dying for this kind of writing

  • Only 99 is that long. What if 99999?

I then responded on the grounds that the project had only 2 requests at that time.Later, I try to write a complete conversion method myself.I tried many times and always had some details not taken into account.

After several tests, the following gives a complete version that I finally wrote for reference:

/**
 * Arabic to Chinese digits,
 * If a number is passed in, it will be processed up to 21 bits, and js with more than 21 bits will automatically represent the number as a scientific count, resulting in loss of precision and processing errors
 * There is no limit to the number string passed in
 * @param {number|string} digit
 */
function toZhDigit(digit) {
  digit = typeof digit === 'number' ? String(digit) : digit;
  const zh = ['Fatal Frame', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
  const unit = ['thousand', 'hundred', 'ten', ''];
  const quot = ['ten thousand', 'Billions', 'Megabytes', 'Beijing', 'Yi', 'Millet', 'Loose', 'ditch', 'Jian', 'just', 'load', 'extremely', 'ganganadi-valuka', 'Monk', 'That's up to him', 'It is beyond logic and above reason', 'Infinite', 'Large Number'];

  let breakLen = Math.ceil(digit.length / 4);
  let notBreakSegment = digit.length % 4 || 4;
  let segment;
  let zeroFlag = [], allZeroFlag = [];
  let result = '';

  while (breakLen > 0) {
    if (!result) { // First Execution
      segment = digit.slice(0, notBreakSegment);
      let segmentLen = segment.length;
      for (let i = 0; i < segmentLen; i++) {
        if (segment[i] != 0) {
          if (zeroFlag.length > 0) {
            result += 'Fatal Frame' + zh[segment[i]] + unit[4 - segmentLen + i];
            // Determine if quot units need to be added
            if (i === segmentLen - 1 && breakLen > 1) {
              result += quot[breakLen - 2];
            }
            zeroFlag.length = 0;
          } else {
            result += zh[segment[i]] + unit[4 - segmentLen + i];
            if (i === segmentLen - 1 && breakLen > 1) {
              result += quot[breakLen - 2];
            }
          }
        } else {
          // Scenario handled as 0
          if (segmentLen == 1) {
            result += zh[segment[i]];
            break;
          }
          zeroFlag.push(segment[i]);
          continue;
        }
      }
    } else {
      segment = digit.slice(notBreakSegment, notBreakSegment + 4);
      notBreakSegment += 4;

      for (let j = 0; j < segment.length; j++) {
        if (segment[j] != 0) {
          if (zeroFlag.length > 0) {
            // The first zeroFlag execution is not zero length, indicating that the last partition has 0 to process
            if (j === 0) {
              result += quot[breakLen - 1] + zh[segment[j]] + unit[j];
            } else {
              result += 'Fatal Frame' + zh[segment[j]] + unit[j];
            }
            zeroFlag.length = 0;
          } else {
            result += zh[segment[j]] + unit[j];
          }
          // Determine if quot units need to be added
          if (j === segment.length - 1 && breakLen > 1) {
            result += quot[breakLen - 2];
          }
        } else {
          // First execution if zeroFlag length is not zero and previous partition is not all zero
          if (j === 0 && zeroFlag.length > 0 && allZeroFlag.length === 0) {
            result += quot[breakLen - 1];
            zeroFlag.length = 0;
            zeroFlag.push(segment[j]);
          } else if (allZeroFlag.length > 0) {
            // Execute to the end
            if (breakLen == 1) {
              result += '';
            } else {
              zeroFlag.length = 0;
            }
          } else {
            zeroFlag.push(segment[j]);
          }

          if (j === segment.length - 1 && zeroFlag.length === 4 && breakLen !== 1) {
            // If executed to the end
            if (breakLen === 1) {
              allZeroFlag.length = 0;
              zeroFlag.length = 0;
              result += quot[breakLen - 1];
            } else {
              allZeroFlag.push(segment[j]);
            }
          }
          continue;
        }
      }
   

    --breakLen;
  }

  return result;
}

About Chinese counting units, you can search on the Internet by yourself.

The general idea of the code above is:

From left to right, the numbers are grouped into 10,000 decimal places, each group is added with the corresponding units (10,000,000,000,000,000,000,...), and then each group is iterated.BreaLen indicates how many groupings can be grouped, and notBreakSegments indicate the length of groupings that are currently processed.There is an if judgment in the while loop, and if there is no result, it means it is the first time to process, so there is some difference in processing.First, on the assignment of a segment, the length of the notBreakSegment is taken from zero for the first time, and then 4 is added to the previous value for each iteration of the notBreakSegment. Second, on the first occasion, it is not necessary to determine whether the previous group is all zero, where zeroFlag represents the number of zeros in each group, ZeallFalG denotes the number of all zero groupings that precede the current grouping.In addition, on the first execution, the case where only 0 was passed in was handled.

Each time segment[i] is processed, it is determined whether the current value is 0 or not, then it is recorded directly to zeroFlag at 0, and then proceeds to the next iteration. If it is not 0, the previous number must first be determined whether it is 0, then quot must be added based on whether the previous 0 is at the end of the previous grouping, and finally the flag needs to be cleared.Bit.If the current grouping is all zero, allZeroFlag is marked, so the next grouping process will need to determine if the previous grouping is all zero
.

Look directly at the code for more details, but don't explain much here.

Next is the conversion of Chinese to Arabic numerals, which is a relatively simple process, where each bit is iterated from right to left, directly up the code:

function zhDigitToArabic(digit) {
  const zh = ['Fatal Frame', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
  const unit = ['thousand', 'hundred', 'ten'];
  const quot = ['ten thousand', 'Billions', 'Megabytes', 'Beijing', 'Yi', 'Millet', 'Loose', 'ditch', 'Jian', 'just', 'load', 'extremely', 'ganganadi-valuka', 'Monk', 'That's up to him', 'It is beyond logic and above reason', 'Infinite', 'Large Number'];
  let result = 0, quotFlag;

  for (let i = digit.length - 1; i >= 0; i--) {
    if (zh.indexOf(digit[i]) > -1) { // number
      if (quotFlag) {
        result += quotFlag * getNumber(digit[i]);
      } else {
        result += getNumber(digit[i]);
      }
    } else if (unit.indexOf(digit[i]) > -1) { // Ten digits
      if (quotFlag) {
        result += quotFlag * getUnit(digit[i]) * getNumber(digit[i - 1]);
      } else {
        result += getUnit(digit[i]) * getNumber(digit[i - 1]);
      }
      --i;
    } else if (quot.indexOf(digit[i]) > -1) { // Decimal point
      if (unit.indexOf(digit[i - 1]) > -1) {
        if (getNumber(digit[i - 1])) {
          result += getQuot(digit[i]) * getNumber(digit[i - 1]);
        } else {
          result += getQuot(digit[i]) * getUnit(digit[i - 1]) * getNumber(digit[i - 2]);
          quotFlag = getQuot(digit[i]);
          --i;
        }
      } else {
        result += getQuot(digit[i]) * getNumber(digit[i - 1]);
        quotFlag = getQuot(digit[i]);
      }
      --i;
    }
  }

  return result;

  // Returns the Arabic numerals corresponding to the Chinese uppercase numerals
  function getNumber(num) {
    for (let i = 0; i < zh.length; i++) {
      if (zh[i] == num) {
        return i;
      }
    }
  }

  // Unit
  function getUnit(num) {
    for (let i = unit.length; i > 0; i--) {
      if (num == unit[i - 1]) {
        return Math.pow(10, 4 - i);
      }
    }
  }

  // Segmentation
  function getQuot(q) {
    for (var i = 0; i < quot.length; i++) {
      if (q == quot[i]) {
        return Math.pow(10, (i + 1) * 4);
      }
    }
  }
}

Note: The code is for reference only. The author only wrote some special and random numbers for testing. It is not guaranteed to be 100% accurate. Please leave a message for feedback if you have any questions.

Keywords: Javascript angular

Added by Flying Sagittarius on Fri, 12 Jul 2019 20:22:28 +0300