Japanese reading of an integerCtCI 16.8: Integer to English phrase in C++Converting an integer number into its word representationInt extension for translating integer to plain EnglishInteger to English ConversionInteger to English challengeConvert an Integer number to readable format in JavaC++17 saturating integer (arithmetic) type libraryMy implementation of a for_each function that traverses a std::container by some step size integer NOne-dimensional Japanese puzzleCtCI 16.8: Integer to English phrase in C++

50% portfolio in single stock, JPM - appropriate for 80 year old?

How do I experimentally measure the surface area of a rock?

What is a dropfile?

Bo Derek in texbook.tex?

Is it possible to use gases instead of liquids as fuel in a rocket engine?

How to determine the degree to which diminished seventh chords and half-diminished seventh chords belong in major scales?

find a condition on B,C so set difference is associative (AB)C=A(BC)

Which battle was the most lopsided result in terms of casualties?

Invalid time zone 'UTC'

Is it possible to get reverse life insurance?

A Star Trek book I read in the eighties, Kirk is shunned for destroying a civilization

Shoe shine shop model in Rust

Equality operator does not get defined for a custom spaceship operator implementation in C++20

How to present boolean options along with selecting exactly 1 of them as "primary"?

Black powder machine gun in an airplane

Why do Muslim refugees seek asylum in Europe and not in rich countries in the Middle East?

What feature could divide the world in two halves and what would be the climate implications?

Interview question: If correlation doesn't imply causation, how do you detect causation?

Can a professor do an internship?

What is the exact definition of an Adaptation under Creative Commons?

When the direction of a movement changes, is the object at rest at some time?

Should I report a security vulnerability?

Just bought HD650's with Scarlet 2i2 solo and it sounds too QUIET

Customize sysctl parameters by user



Japanese reading of an integer


CtCI 16.8: Integer to English phrase in C++Converting an integer number into its word representationInt extension for translating integer to plain EnglishInteger to English ConversionInteger to English challengeConvert an Integer number to readable format in JavaC++17 saturating integer (arithmetic) type libraryMy implementation of a for_each function that traverses a std::container by some step size integer NOne-dimensional Japanese puzzleCtCI 16.8: Integer to English phrase in C++






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;









26














$begingroup$


Inspired by CtCI 16.8: Integer to English phrase in C++, I wrote a program to show the Japanese reading of an integer (positive, negative, or zero). The Japanese is written in Hepburn romanization to avoid encoding problems. Also, traditional Hepburn is used to avoid macrons.



Unlike English, Japanese has sound changes when two words come together. The details are given at the end of the question.



The program handles integers $n$ in the range $-2^63 le n < 2^63$.



Code



/**
* Integer to Japanese reading
*
* Japanese reading is written in Hepburn Roomaji. Traditional
* Hepburn is used to avoid the need of macrons.
*/

#include <cassert>
#include <cstdint>
#include <iostream>
#include <string>
#include <vector>

using number_t = std::int_fast64_t;

const std::vector<std::string> magnitudes =
"", "man", "oku", "choo", "kee",
;
const std::vector<std::string> thousands =
"", "sen", "nisen", "sanzen", "yonsen",
"gosen", "rokusen", "nanasen", "hassen", "kyuusen",
;
const std::vector<std::string> hundreds =
"", "hyaku", "nihyaku", "sanbyaku", "yonhyaku",
"gohyaku", "roppyaku", "nanahyaku", "happyaku", "kyuuhyaku",
;
const std::vector<std::string> tens =
"", "juu", "nijuu", "sanjuu", "yonjuu",
"gojuu", "rokujuu", "nanajuu", "hachijuu", "kyuujuu",
;
const std::vector<std::string> ones =
"", "ichi", "ni", "san", "yon",
"go", "roku", "nana", "hachi", "kyuu",
;

// returns 10000^n
constexpr number_t magnitude(std::size_t n)

number_t result = 1;
while (n--)
result *= 10000;
return result;


constexpr bool is_vowel(char c)

switch (c)
case 'a': case 'e': case 'i': case 'o': case 'u': case 'y':
return true;
default:
return false;



// joins two strings according to Japanese rules
void push(std::string& lhs, const std::string& rhs)

if (lhs.back() == 'n' && is_vowel(rhs.front()))
lhs += ''';
lhs += rhs;


// converts nonnegative numbers less than 10000
std::string group_name(number_t number)

assert(0 <= number && number < 10000);
std::string result = thousands[number / 1000];
number %= 1000;
push(result, hundreds[number / 100]);
number %= 100;
push(result, tens[number / 10]);
number %= 10;
push(result, ones[number]);
return result;


std::string to_Japanese(number_t number)

if (number == 0)
return "zero";

std::string result;
if (number < 0)
result = "mainasu";
number = -number;


number_t mag = magnitude(magnitudes.size() - 1);
for (std::size_t i = magnitudes.size(); i-- > 0; mag /= 10000)
if (auto group = number / mag; group > 0)
push(result, group_name(group));
push(result, magnitudes[i]);

number %= mag;

return result;


int main()

for (number_t number; std::cin >> number;)
std::cout << to_Japanese(number) << "n";



Example session



0
zero
1
ichi
2
ni
3
san
6789678967896789
rokusennanahyakuhachijuukyuuchoorokusennanahyakuhachijuukyuuokurokusennanahyakuhachijuukyuumanrokusennanahyakuhachijuukyuu
-1234567898765432
mainasusennihyakusanjuuyonchoogosenroppyakunanajuuhachiokukyuusenhappyakunanajuurokumangosen'yonhyakusanjuuni


Japanese numerals



(You can skip this part if you are familiar with Japanese.)



In the following table, red entries involve sound change.



beginarrayll
textNumber & textJapanese reading \
1 & text一 (ichi) \
2 & text二 (ni) \
3 & text三 (san) \
4 & text四 (yon) \
5 & text五 (go) \
6 & text六 (roku) \
7 & text七 (nana) \
8 & text八 (hachi) \
9 & text九 (kyuu) \
10 & text十 (juu) \
20 & text二十 (nijuu) \
30 & text三十 (sanjuu) \
40 & text四十 (yonjuu) \
50 & text五十 (gojuu) \
60 & text六十 (rokujuu) \
70 & text七十 (nanajuu) \
80 & text八十 (hachijuu) \
90 & text九十 (kyuujuu) \
100 & text百 (hyaku) \
200 & text二百 (nihyaku) \
300 & text三百 colorredtext(sanbyaku) \
400 & text四百 (yonhyaku) \
500 & text五百 (gohyaku) \
600 & text六百 colorredtext(roppyaku) \
700 & text七百 (nanahyaku) \
800 & text八百 colorredtext(happyaku) \
900 & text九百 (kyuuhyaku) \
1000 & text千 (sen) \
2000 & text二千 (nisen) \
3000 & text三千 colorredtext(sanzen) \
4000 & text四千 (yonsen) \
5000 & text五千 (gosen) \
6000 & text六千 (rokusen) \
7000 & text七千 (nanasen) \
8000 & text八千 colorredtext(hassen) \
9000 & text九千 (kyuusen) \
endarray



Larger numbers are considered the sums of smaller numbers. For example:



beginarrayccccccc
2019 & = & 2000 & + & 10 & + & 9 \
text二千十九 (nisenjuukyuu) & &
text二千 (nisen) & &
text十 (juu) & &
text九 (kyuu)
endarray



The missing hundred place is simply ignored.



Four digits are considered a group, unlike English, where three digits are a group. The group markers are:



beginarrayccc
10^4 & 10^8 & 10^12 & 10^16 \
text万 (man) & text億 (oku) & text兆 (choo) & text京 (kee)
endarray



For example, $1,2345,6789$ is read as 一億二千三百四十五万六千七百八十九 (ichioku nisensanbyakuyonjuugoman rokusennanahyakuhachijuukyuu). (The spaces are for ease of recognition only.) Note that 一 (ichi) is required before these group markers, unlike 十 (juu), 百 (hyaku), and 千 (sen).



0 is ゼロ (zero).



A negative integer $-n$ is read as マイナス (mainasu) followed by its absolute value $n$. For example, -5 is read as マイナス五 (mainasugo), because 5 is read as 五 (go).



When two syllables are joined, if the first syllable ends with "n" and the second starts with one of "aeiouy", then a separator ' is added between. For example, 1001 is 千一 (sen'ichi) and 1004 is 千四 (sen'yon).










share|improve this question












$endgroup$





















    26














    $begingroup$


    Inspired by CtCI 16.8: Integer to English phrase in C++, I wrote a program to show the Japanese reading of an integer (positive, negative, or zero). The Japanese is written in Hepburn romanization to avoid encoding problems. Also, traditional Hepburn is used to avoid macrons.



    Unlike English, Japanese has sound changes when two words come together. The details are given at the end of the question.



    The program handles integers $n$ in the range $-2^63 le n < 2^63$.



    Code



    /**
    * Integer to Japanese reading
    *
    * Japanese reading is written in Hepburn Roomaji. Traditional
    * Hepburn is used to avoid the need of macrons.
    */

    #include <cassert>
    #include <cstdint>
    #include <iostream>
    #include <string>
    #include <vector>

    using number_t = std::int_fast64_t;

    const std::vector<std::string> magnitudes =
    "", "man", "oku", "choo", "kee",
    ;
    const std::vector<std::string> thousands =
    "", "sen", "nisen", "sanzen", "yonsen",
    "gosen", "rokusen", "nanasen", "hassen", "kyuusen",
    ;
    const std::vector<std::string> hundreds =
    "", "hyaku", "nihyaku", "sanbyaku", "yonhyaku",
    "gohyaku", "roppyaku", "nanahyaku", "happyaku", "kyuuhyaku",
    ;
    const std::vector<std::string> tens =
    "", "juu", "nijuu", "sanjuu", "yonjuu",
    "gojuu", "rokujuu", "nanajuu", "hachijuu", "kyuujuu",
    ;
    const std::vector<std::string> ones =
    "", "ichi", "ni", "san", "yon",
    "go", "roku", "nana", "hachi", "kyuu",
    ;

    // returns 10000^n
    constexpr number_t magnitude(std::size_t n)

    number_t result = 1;
    while (n--)
    result *= 10000;
    return result;


    constexpr bool is_vowel(char c)

    switch (c)
    case 'a': case 'e': case 'i': case 'o': case 'u': case 'y':
    return true;
    default:
    return false;



    // joins two strings according to Japanese rules
    void push(std::string& lhs, const std::string& rhs)

    if (lhs.back() == 'n' && is_vowel(rhs.front()))
    lhs += ''';
    lhs += rhs;


    // converts nonnegative numbers less than 10000
    std::string group_name(number_t number)

    assert(0 <= number && number < 10000);
    std::string result = thousands[number / 1000];
    number %= 1000;
    push(result, hundreds[number / 100]);
    number %= 100;
    push(result, tens[number / 10]);
    number %= 10;
    push(result, ones[number]);
    return result;


    std::string to_Japanese(number_t number)

    if (number == 0)
    return "zero";

    std::string result;
    if (number < 0)
    result = "mainasu";
    number = -number;


    number_t mag = magnitude(magnitudes.size() - 1);
    for (std::size_t i = magnitudes.size(); i-- > 0; mag /= 10000)
    if (auto group = number / mag; group > 0)
    push(result, group_name(group));
    push(result, magnitudes[i]);

    number %= mag;

    return result;


    int main()

    for (number_t number; std::cin >> number;)
    std::cout << to_Japanese(number) << "n";



    Example session



    0
    zero
    1
    ichi
    2
    ni
    3
    san
    6789678967896789
    rokusennanahyakuhachijuukyuuchoorokusennanahyakuhachijuukyuuokurokusennanahyakuhachijuukyuumanrokusennanahyakuhachijuukyuu
    -1234567898765432
    mainasusennihyakusanjuuyonchoogosenroppyakunanajuuhachiokukyuusenhappyakunanajuurokumangosen'yonhyakusanjuuni


    Japanese numerals



    (You can skip this part if you are familiar with Japanese.)



    In the following table, red entries involve sound change.



    beginarrayll
    textNumber & textJapanese reading \
    1 & text一 (ichi) \
    2 & text二 (ni) \
    3 & text三 (san) \
    4 & text四 (yon) \
    5 & text五 (go) \
    6 & text六 (roku) \
    7 & text七 (nana) \
    8 & text八 (hachi) \
    9 & text九 (kyuu) \
    10 & text十 (juu) \
    20 & text二十 (nijuu) \
    30 & text三十 (sanjuu) \
    40 & text四十 (yonjuu) \
    50 & text五十 (gojuu) \
    60 & text六十 (rokujuu) \
    70 & text七十 (nanajuu) \
    80 & text八十 (hachijuu) \
    90 & text九十 (kyuujuu) \
    100 & text百 (hyaku) \
    200 & text二百 (nihyaku) \
    300 & text三百 colorredtext(sanbyaku) \
    400 & text四百 (yonhyaku) \
    500 & text五百 (gohyaku) \
    600 & text六百 colorredtext(roppyaku) \
    700 & text七百 (nanahyaku) \
    800 & text八百 colorredtext(happyaku) \
    900 & text九百 (kyuuhyaku) \
    1000 & text千 (sen) \
    2000 & text二千 (nisen) \
    3000 & text三千 colorredtext(sanzen) \
    4000 & text四千 (yonsen) \
    5000 & text五千 (gosen) \
    6000 & text六千 (rokusen) \
    7000 & text七千 (nanasen) \
    8000 & text八千 colorredtext(hassen) \
    9000 & text九千 (kyuusen) \
    endarray



    Larger numbers are considered the sums of smaller numbers. For example:



    beginarrayccccccc
    2019 & = & 2000 & + & 10 & + & 9 \
    text二千十九 (nisenjuukyuu) & &
    text二千 (nisen) & &
    text十 (juu) & &
    text九 (kyuu)
    endarray



    The missing hundred place is simply ignored.



    Four digits are considered a group, unlike English, where three digits are a group. The group markers are:



    beginarrayccc
    10^4 & 10^8 & 10^12 & 10^16 \
    text万 (man) & text億 (oku) & text兆 (choo) & text京 (kee)
    endarray



    For example, $1,2345,6789$ is read as 一億二千三百四十五万六千七百八十九 (ichioku nisensanbyakuyonjuugoman rokusennanahyakuhachijuukyuu). (The spaces are for ease of recognition only.) Note that 一 (ichi) is required before these group markers, unlike 十 (juu), 百 (hyaku), and 千 (sen).



    0 is ゼロ (zero).



    A negative integer $-n$ is read as マイナス (mainasu) followed by its absolute value $n$. For example, -5 is read as マイナス五 (mainasugo), because 5 is read as 五 (go).



    When two syllables are joined, if the first syllable ends with "n" and the second starts with one of "aeiouy", then a separator ' is added between. For example, 1001 is 千一 (sen'ichi) and 1004 is 千四 (sen'yon).










    share|improve this question












    $endgroup$

















      26












      26








      26


      3



      $begingroup$


      Inspired by CtCI 16.8: Integer to English phrase in C++, I wrote a program to show the Japanese reading of an integer (positive, negative, or zero). The Japanese is written in Hepburn romanization to avoid encoding problems. Also, traditional Hepburn is used to avoid macrons.



      Unlike English, Japanese has sound changes when two words come together. The details are given at the end of the question.



      The program handles integers $n$ in the range $-2^63 le n < 2^63$.



      Code



      /**
      * Integer to Japanese reading
      *
      * Japanese reading is written in Hepburn Roomaji. Traditional
      * Hepburn is used to avoid the need of macrons.
      */

      #include <cassert>
      #include <cstdint>
      #include <iostream>
      #include <string>
      #include <vector>

      using number_t = std::int_fast64_t;

      const std::vector<std::string> magnitudes =
      "", "man", "oku", "choo", "kee",
      ;
      const std::vector<std::string> thousands =
      "", "sen", "nisen", "sanzen", "yonsen",
      "gosen", "rokusen", "nanasen", "hassen", "kyuusen",
      ;
      const std::vector<std::string> hundreds =
      "", "hyaku", "nihyaku", "sanbyaku", "yonhyaku",
      "gohyaku", "roppyaku", "nanahyaku", "happyaku", "kyuuhyaku",
      ;
      const std::vector<std::string> tens =
      "", "juu", "nijuu", "sanjuu", "yonjuu",
      "gojuu", "rokujuu", "nanajuu", "hachijuu", "kyuujuu",
      ;
      const std::vector<std::string> ones =
      "", "ichi", "ni", "san", "yon",
      "go", "roku", "nana", "hachi", "kyuu",
      ;

      // returns 10000^n
      constexpr number_t magnitude(std::size_t n)

      number_t result = 1;
      while (n--)
      result *= 10000;
      return result;


      constexpr bool is_vowel(char c)

      switch (c)
      case 'a': case 'e': case 'i': case 'o': case 'u': case 'y':
      return true;
      default:
      return false;



      // joins two strings according to Japanese rules
      void push(std::string& lhs, const std::string& rhs)

      if (lhs.back() == 'n' && is_vowel(rhs.front()))
      lhs += ''';
      lhs += rhs;


      // converts nonnegative numbers less than 10000
      std::string group_name(number_t number)

      assert(0 <= number && number < 10000);
      std::string result = thousands[number / 1000];
      number %= 1000;
      push(result, hundreds[number / 100]);
      number %= 100;
      push(result, tens[number / 10]);
      number %= 10;
      push(result, ones[number]);
      return result;


      std::string to_Japanese(number_t number)

      if (number == 0)
      return "zero";

      std::string result;
      if (number < 0)
      result = "mainasu";
      number = -number;


      number_t mag = magnitude(magnitudes.size() - 1);
      for (std::size_t i = magnitudes.size(); i-- > 0; mag /= 10000)
      if (auto group = number / mag; group > 0)
      push(result, group_name(group));
      push(result, magnitudes[i]);

      number %= mag;

      return result;


      int main()

      for (number_t number; std::cin >> number;)
      std::cout << to_Japanese(number) << "n";



      Example session



      0
      zero
      1
      ichi
      2
      ni
      3
      san
      6789678967896789
      rokusennanahyakuhachijuukyuuchoorokusennanahyakuhachijuukyuuokurokusennanahyakuhachijuukyuumanrokusennanahyakuhachijuukyuu
      -1234567898765432
      mainasusennihyakusanjuuyonchoogosenroppyakunanajuuhachiokukyuusenhappyakunanajuurokumangosen'yonhyakusanjuuni


      Japanese numerals



      (You can skip this part if you are familiar with Japanese.)



      In the following table, red entries involve sound change.



      beginarrayll
      textNumber & textJapanese reading \
      1 & text一 (ichi) \
      2 & text二 (ni) \
      3 & text三 (san) \
      4 & text四 (yon) \
      5 & text五 (go) \
      6 & text六 (roku) \
      7 & text七 (nana) \
      8 & text八 (hachi) \
      9 & text九 (kyuu) \
      10 & text十 (juu) \
      20 & text二十 (nijuu) \
      30 & text三十 (sanjuu) \
      40 & text四十 (yonjuu) \
      50 & text五十 (gojuu) \
      60 & text六十 (rokujuu) \
      70 & text七十 (nanajuu) \
      80 & text八十 (hachijuu) \
      90 & text九十 (kyuujuu) \
      100 & text百 (hyaku) \
      200 & text二百 (nihyaku) \
      300 & text三百 colorredtext(sanbyaku) \
      400 & text四百 (yonhyaku) \
      500 & text五百 (gohyaku) \
      600 & text六百 colorredtext(roppyaku) \
      700 & text七百 (nanahyaku) \
      800 & text八百 colorredtext(happyaku) \
      900 & text九百 (kyuuhyaku) \
      1000 & text千 (sen) \
      2000 & text二千 (nisen) \
      3000 & text三千 colorredtext(sanzen) \
      4000 & text四千 (yonsen) \
      5000 & text五千 (gosen) \
      6000 & text六千 (rokusen) \
      7000 & text七千 (nanasen) \
      8000 & text八千 colorredtext(hassen) \
      9000 & text九千 (kyuusen) \
      endarray



      Larger numbers are considered the sums of smaller numbers. For example:



      beginarrayccccccc
      2019 & = & 2000 & + & 10 & + & 9 \
      text二千十九 (nisenjuukyuu) & &
      text二千 (nisen) & &
      text十 (juu) & &
      text九 (kyuu)
      endarray



      The missing hundred place is simply ignored.



      Four digits are considered a group, unlike English, where three digits are a group. The group markers are:



      beginarrayccc
      10^4 & 10^8 & 10^12 & 10^16 \
      text万 (man) & text億 (oku) & text兆 (choo) & text京 (kee)
      endarray



      For example, $1,2345,6789$ is read as 一億二千三百四十五万六千七百八十九 (ichioku nisensanbyakuyonjuugoman rokusennanahyakuhachijuukyuu). (The spaces are for ease of recognition only.) Note that 一 (ichi) is required before these group markers, unlike 十 (juu), 百 (hyaku), and 千 (sen).



      0 is ゼロ (zero).



      A negative integer $-n$ is read as マイナス (mainasu) followed by its absolute value $n$. For example, -5 is read as マイナス五 (mainasugo), because 5 is read as 五 (go).



      When two syllables are joined, if the first syllable ends with "n" and the second starts with one of "aeiouy", then a separator ' is added between. For example, 1001 is 千一 (sen'ichi) and 1004 is 千四 (sen'yon).










      share|improve this question












      $endgroup$




      Inspired by CtCI 16.8: Integer to English phrase in C++, I wrote a program to show the Japanese reading of an integer (positive, negative, or zero). The Japanese is written in Hepburn romanization to avoid encoding problems. Also, traditional Hepburn is used to avoid macrons.



      Unlike English, Japanese has sound changes when two words come together. The details are given at the end of the question.



      The program handles integers $n$ in the range $-2^63 le n < 2^63$.



      Code



      /**
      * Integer to Japanese reading
      *
      * Japanese reading is written in Hepburn Roomaji. Traditional
      * Hepburn is used to avoid the need of macrons.
      */

      #include <cassert>
      #include <cstdint>
      #include <iostream>
      #include <string>
      #include <vector>

      using number_t = std::int_fast64_t;

      const std::vector<std::string> magnitudes =
      "", "man", "oku", "choo", "kee",
      ;
      const std::vector<std::string> thousands =
      "", "sen", "nisen", "sanzen", "yonsen",
      "gosen", "rokusen", "nanasen", "hassen", "kyuusen",
      ;
      const std::vector<std::string> hundreds =
      "", "hyaku", "nihyaku", "sanbyaku", "yonhyaku",
      "gohyaku", "roppyaku", "nanahyaku", "happyaku", "kyuuhyaku",
      ;
      const std::vector<std::string> tens =
      "", "juu", "nijuu", "sanjuu", "yonjuu",
      "gojuu", "rokujuu", "nanajuu", "hachijuu", "kyuujuu",
      ;
      const std::vector<std::string> ones =
      "", "ichi", "ni", "san", "yon",
      "go", "roku", "nana", "hachi", "kyuu",
      ;

      // returns 10000^n
      constexpr number_t magnitude(std::size_t n)

      number_t result = 1;
      while (n--)
      result *= 10000;
      return result;


      constexpr bool is_vowel(char c)

      switch (c)
      case 'a': case 'e': case 'i': case 'o': case 'u': case 'y':
      return true;
      default:
      return false;



      // joins two strings according to Japanese rules
      void push(std::string& lhs, const std::string& rhs)

      if (lhs.back() == 'n' && is_vowel(rhs.front()))
      lhs += ''';
      lhs += rhs;


      // converts nonnegative numbers less than 10000
      std::string group_name(number_t number)

      assert(0 <= number && number < 10000);
      std::string result = thousands[number / 1000];
      number %= 1000;
      push(result, hundreds[number / 100]);
      number %= 100;
      push(result, tens[number / 10]);
      number %= 10;
      push(result, ones[number]);
      return result;


      std::string to_Japanese(number_t number)

      if (number == 0)
      return "zero";

      std::string result;
      if (number < 0)
      result = "mainasu";
      number = -number;


      number_t mag = magnitude(magnitudes.size() - 1);
      for (std::size_t i = magnitudes.size(); i-- > 0; mag /= 10000)
      if (auto group = number / mag; group > 0)
      push(result, group_name(group));
      push(result, magnitudes[i]);

      number %= mag;

      return result;


      int main()

      for (number_t number; std::cin >> number;)
      std::cout << to_Japanese(number) << "n";



      Example session



      0
      zero
      1
      ichi
      2
      ni
      3
      san
      6789678967896789
      rokusennanahyakuhachijuukyuuchoorokusennanahyakuhachijuukyuuokurokusennanahyakuhachijuukyuumanrokusennanahyakuhachijuukyuu
      -1234567898765432
      mainasusennihyakusanjuuyonchoogosenroppyakunanajuuhachiokukyuusenhappyakunanajuurokumangosen'yonhyakusanjuuni


      Japanese numerals



      (You can skip this part if you are familiar with Japanese.)



      In the following table, red entries involve sound change.



      beginarrayll
      textNumber & textJapanese reading \
      1 & text一 (ichi) \
      2 & text二 (ni) \
      3 & text三 (san) \
      4 & text四 (yon) \
      5 & text五 (go) \
      6 & text六 (roku) \
      7 & text七 (nana) \
      8 & text八 (hachi) \
      9 & text九 (kyuu) \
      10 & text十 (juu) \
      20 & text二十 (nijuu) \
      30 & text三十 (sanjuu) \
      40 & text四十 (yonjuu) \
      50 & text五十 (gojuu) \
      60 & text六十 (rokujuu) \
      70 & text七十 (nanajuu) \
      80 & text八十 (hachijuu) \
      90 & text九十 (kyuujuu) \
      100 & text百 (hyaku) \
      200 & text二百 (nihyaku) \
      300 & text三百 colorredtext(sanbyaku) \
      400 & text四百 (yonhyaku) \
      500 & text五百 (gohyaku) \
      600 & text六百 colorredtext(roppyaku) \
      700 & text七百 (nanahyaku) \
      800 & text八百 colorredtext(happyaku) \
      900 & text九百 (kyuuhyaku) \
      1000 & text千 (sen) \
      2000 & text二千 (nisen) \
      3000 & text三千 colorredtext(sanzen) \
      4000 & text四千 (yonsen) \
      5000 & text五千 (gosen) \
      6000 & text六千 (rokusen) \
      7000 & text七千 (nanasen) \
      8000 & text八千 colorredtext(hassen) \
      9000 & text九千 (kyuusen) \
      endarray



      Larger numbers are considered the sums of smaller numbers. For example:



      beginarrayccccccc
      2019 & = & 2000 & + & 10 & + & 9 \
      text二千十九 (nisenjuukyuu) & &
      text二千 (nisen) & &
      text十 (juu) & &
      text九 (kyuu)
      endarray



      The missing hundred place is simply ignored.



      Four digits are considered a group, unlike English, where three digits are a group. The group markers are:



      beginarrayccc
      10^4 & 10^8 & 10^12 & 10^16 \
      text万 (man) & text億 (oku) & text兆 (choo) & text京 (kee)
      endarray



      For example, $1,2345,6789$ is read as 一億二千三百四十五万六千七百八十九 (ichioku nisensanbyakuyonjuugoman rokusennanahyakuhachijuukyuu). (The spaces are for ease of recognition only.) Note that 一 (ichi) is required before these group markers, unlike 十 (juu), 百 (hyaku), and 千 (sen).



      0 is ゼロ (zero).



      A negative integer $-n$ is read as マイナス (mainasu) followed by its absolute value $n$. For example, -5 is read as マイナス五 (mainasugo), because 5 is read as 五 (go).



      When two syllables are joined, if the first syllable ends with "n" and the second starts with one of "aeiouy", then a separator ' is added between. For example, 1001 is 千一 (sen'ichi) and 1004 is 千四 (sen'yon).







      c++ c++17 numbers-to-words






      share|improve this question
















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jul 28 at 11:53







      L. F.

















      asked Jul 28 at 11:44









      L. F.L. F.

      3,7471 gold badge7 silver badges37 bronze badges




      3,7471 gold badge7 silver badges37 bronze badges























          5 Answers
          5






          active

          oldest

          votes


















          8
















          $begingroup$

          The push function may invoke undefined behavior. When you create a new std::string, I don't think it is guaranteed to be null-terminated since that would incur a runtime cost for no benefit other than C compatibility. Only after calling c_str() the terminating null character is there. Because the string is really empty, calling back() accesses an out-of-bounds element.



          You claim that your code works for $-2^63$ but you didn't add that number as a test case. I would expect it to not work since -(-2**63) is still negative.



          Besides these two issues, your code reads well and is easy to understand. Adding the additional documentation was a very good idea for everyone not fluent in Japanese.






          share|improve this answer












          $endgroup$














          • $begingroup$
            I see. The problem is that back accesses the nonexistent element. (The terminating null character doesn't change that.)
            $endgroup$
            – L. F.
            Jul 29 at 5:22










          • $begingroup$
            @L.F. Yes, in reality most std::string implementations will have a terminating 0 byte at all times. And in fact C++11 and later requires that operator[] with pos=size() references the terminating 0. What makes back() UB is that en.cppreference.com/w/cpp/string/basic_string/back says it's UB when .empty() == true. And moreover that it's equivalent to operator[](size() - 1) which would wrap the unsigned position.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:28










          • $begingroup$
            The code definitely needs a check. Also, operator[](size() - 1) only applies if empty() is false, so wrapping is irrelevant I guess.
            $endgroup$
            – L. F.
            Jul 29 at 6:31










          • $begingroup$
            In practice g++ -O0 with libstdc++ (on Arch Linux) gives 0 when doing .back() on an empty std::string, so it doesn't help you detect this bug by crashing on that UB.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:31






          • 3




            $begingroup$
            @L.F.: fun facts: Legality of COW std::string implementation in C++11 shows how some of the new requirements in C++11 basically make efficient COW implementation of std::string impossible. With .data() also requiring a 0-terminated string, the obvious/intended implementation is to always maintain that so .data() and .c_str() can be a no-op that just returns one of the class member vars.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:36


















          15
















          $begingroup$

          Your magnitudes should be chou and kei (as in the supercomputer, as an aside). Also, to_Japanese() would be better named to_romaji(). As an exercise, you could try to_Japanese(number, KANJI|HIRAGANA|ROMAJI) also.



          Furthermore, it's icchou, not ichichou, and ikkei, not ichikei.






          share|improve this answer










          $endgroup$










          • 1




            $begingroup$
            Thank you for correcting my Japanese! I am a beginner and sorry for the mistakes. Regarding chou vs choo: what I learned is that when おう is a long "o", it is written as "oo" instead of "ou". I figured out that different romaji systems differ on this. And "ichichou" is so silly ;)
            $endgroup$
            – L. F.
            Jul 29 at 0:50






          • 2




            $begingroup$
            Yes, there's lots of different romaji versions - I looked up the most common Hepburn, and choo is correct, although I always use chou as it's IME-friendly, but then sennana would be typed sennnana. We're now straying into Japanese Language territory...
            $endgroup$
            – Ken Y-N
            Jul 29 at 5:59


















          9
















          $begingroup$

          I think it would be better to generate the 漢字 versions of the numbers, as it's more useful in general. Make a separate class responsible for romanization (or phonetic conversion in general so it can support kana).



          Using kanji also allows for somewhat trivially adding support for formal numbers (大字), which is kind of cool/useful.



          I would also recommend adding support for breaking up the romaji sequences as reading very large numbers in romaji with no spaces is not at all fun. It could be an optional flag. A natural place to add spaces would be between magnitudes at least, or maybe between all of the various groupings you've already put together (ones, tens, hundreds, etc.).



          As for using romaji to avoid encoding issues, I recommending biting the bullet and learning how to support Unicode correctly as it will be extremely useful.






          share|improve this answer










          $endgroup$










          • 1




            $begingroup$
            Insightful. Although romanization is nontrivial AFAIK since one kanji can have multiple readings ... Spaces in between romaji is also a good idea.
            $endgroup$
            – L. F.
            Jul 29 at 3:25






          • 1




            $begingroup$
            @L.F. romanization doesn't have to support the entirety of Japanese, as this code is number focused, and you've already decided on the readings for each of the kanji involved anyway (or rather; there's only one right answer for these in this context); and that means katakana and hiragana phonetic readings are just as easy at that point.
            $endgroup$
            – briantist
            Jul 29 at 3:30


















          7
















          $begingroup$

          I know in that in English that each word would be separate where the program is printing the all of the numbers merged together. Is this the actual functionality in Japanese?



          Since the code might be useful in many places it might be better of the translation code as in a class.



          Use of Vertical Space

          Generally code is easier to read and maintain when only one value is on a line. This would apply to the initialization of the vectors and the switch statement in the function is_vowel(). For maintenance reasons it is much easier to insert a line where it needs to be than it is to add a value to a comma separated list.



          is_vowel function

          There would be less code if the vowels were in a std::map rather than a switch statement. Here are discussions on stack overflow and software engineering.



          This portion of the answer has been modified to remove the statement that there might be a performance improvement using std::map. If map used a simple index into an array that might be true, however it is not a simple index into an array.



          Assert
          Assert statements are generally used for debugging purposes and terminate the program. Assert statements may be removed when the code is compiled without debugging as well. I don't expect to see asserts in production level code because it implies that the code is not yet debugged.






          share|improve this answer












          $endgroup$










          • 12




            $begingroup$
            "There would be less code and the performance might be better if the vowels were in a std::map rather than a switch statement." - do you have anything to support a claim that std::map is faster than a raw switch statement? Because I very much doubt that.
            $endgroup$
            – Tomáš Zato
            Jul 29 at 9:26






          • 5




            $begingroup$
            ^ Agreed with Tomas. Provide proof. std::map is dynamically-allocated, node-based, and definitely not cache friendly
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:41






          • 10




            $begingroup$
            "Assert statements are generally used for debugging purposes and throw an exception." - NO. Assert statements exist to test preconditions. Exceptions have nothing to do with preconditions. This answer is harmful.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:42







          • 7




            $begingroup$
            Failed assert()s do not throw - they terminate the program.
            $endgroup$
            – Toby Speight
            Jul 29 at 11:14






          • 6




            $begingroup$
            "It is generally better to use if statements that provide error messages rather than assert statements." - This is still severely wrong and harmful. They have completely different use cases. Assert -> precondition check, contract breakage, unrecoverable error. if statement + error -> recoverable error, can be usually handled by a human.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 13:15


















          4
















          $begingroup$

          You use of std::vector<std::string> for the arrays of string constants is wasteful. Both std::vector and std::string are dynamic types that can potentially allocate. A much more lightweight choice would be constexpr std::array<const char*> or constexpr std::array<std::string_view>.






          share|improve this answer










          $endgroup$














          • $begingroup$
            Fair point. string is probably not dynamic in this case due to SSO, but vector is quite wasteful.
            $endgroup$
            – L. F.
            Jul 29 at 10:42






          • 1




            $begingroup$
            Still, I like using the most minimal tool for the job whenever possible. Even if the constants are going to fit in SSO, it's good practice to use std::string_view or const char*. The compiler will also very likely be able to optimize better.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:44












          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );














          draft saved

          draft discarded
















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f225082%2fjapanese-reading-of-an-integer%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown


























          5 Answers
          5






          active

          oldest

          votes








          5 Answers
          5






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          8
















          $begingroup$

          The push function may invoke undefined behavior. When you create a new std::string, I don't think it is guaranteed to be null-terminated since that would incur a runtime cost for no benefit other than C compatibility. Only after calling c_str() the terminating null character is there. Because the string is really empty, calling back() accesses an out-of-bounds element.



          You claim that your code works for $-2^63$ but you didn't add that number as a test case. I would expect it to not work since -(-2**63) is still negative.



          Besides these two issues, your code reads well and is easy to understand. Adding the additional documentation was a very good idea for everyone not fluent in Japanese.






          share|improve this answer












          $endgroup$














          • $begingroup$
            I see. The problem is that back accesses the nonexistent element. (The terminating null character doesn't change that.)
            $endgroup$
            – L. F.
            Jul 29 at 5:22










          • $begingroup$
            @L.F. Yes, in reality most std::string implementations will have a terminating 0 byte at all times. And in fact C++11 and later requires that operator[] with pos=size() references the terminating 0. What makes back() UB is that en.cppreference.com/w/cpp/string/basic_string/back says it's UB when .empty() == true. And moreover that it's equivalent to operator[](size() - 1) which would wrap the unsigned position.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:28










          • $begingroup$
            The code definitely needs a check. Also, operator[](size() - 1) only applies if empty() is false, so wrapping is irrelevant I guess.
            $endgroup$
            – L. F.
            Jul 29 at 6:31










          • $begingroup$
            In practice g++ -O0 with libstdc++ (on Arch Linux) gives 0 when doing .back() on an empty std::string, so it doesn't help you detect this bug by crashing on that UB.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:31






          • 3




            $begingroup$
            @L.F.: fun facts: Legality of COW std::string implementation in C++11 shows how some of the new requirements in C++11 basically make efficient COW implementation of std::string impossible. With .data() also requiring a 0-terminated string, the obvious/intended implementation is to always maintain that so .data() and .c_str() can be a no-op that just returns one of the class member vars.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:36















          8
















          $begingroup$

          The push function may invoke undefined behavior. When you create a new std::string, I don't think it is guaranteed to be null-terminated since that would incur a runtime cost for no benefit other than C compatibility. Only after calling c_str() the terminating null character is there. Because the string is really empty, calling back() accesses an out-of-bounds element.



          You claim that your code works for $-2^63$ but you didn't add that number as a test case. I would expect it to not work since -(-2**63) is still negative.



          Besides these two issues, your code reads well and is easy to understand. Adding the additional documentation was a very good idea for everyone not fluent in Japanese.






          share|improve this answer












          $endgroup$














          • $begingroup$
            I see. The problem is that back accesses the nonexistent element. (The terminating null character doesn't change that.)
            $endgroup$
            – L. F.
            Jul 29 at 5:22










          • $begingroup$
            @L.F. Yes, in reality most std::string implementations will have a terminating 0 byte at all times. And in fact C++11 and later requires that operator[] with pos=size() references the terminating 0. What makes back() UB is that en.cppreference.com/w/cpp/string/basic_string/back says it's UB when .empty() == true. And moreover that it's equivalent to operator[](size() - 1) which would wrap the unsigned position.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:28










          • $begingroup$
            The code definitely needs a check. Also, operator[](size() - 1) only applies if empty() is false, so wrapping is irrelevant I guess.
            $endgroup$
            – L. F.
            Jul 29 at 6:31










          • $begingroup$
            In practice g++ -O0 with libstdc++ (on Arch Linux) gives 0 when doing .back() on an empty std::string, so it doesn't help you detect this bug by crashing on that UB.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:31






          • 3




            $begingroup$
            @L.F.: fun facts: Legality of COW std::string implementation in C++11 shows how some of the new requirements in C++11 basically make efficient COW implementation of std::string impossible. With .data() also requiring a 0-terminated string, the obvious/intended implementation is to always maintain that so .data() and .c_str() can be a no-op that just returns one of the class member vars.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:36













          8














          8










          8







          $begingroup$

          The push function may invoke undefined behavior. When you create a new std::string, I don't think it is guaranteed to be null-terminated since that would incur a runtime cost for no benefit other than C compatibility. Only after calling c_str() the terminating null character is there. Because the string is really empty, calling back() accesses an out-of-bounds element.



          You claim that your code works for $-2^63$ but you didn't add that number as a test case. I would expect it to not work since -(-2**63) is still negative.



          Besides these two issues, your code reads well and is easy to understand. Adding the additional documentation was a very good idea for everyone not fluent in Japanese.






          share|improve this answer












          $endgroup$



          The push function may invoke undefined behavior. When you create a new std::string, I don't think it is guaranteed to be null-terminated since that would incur a runtime cost for no benefit other than C compatibility. Only after calling c_str() the terminating null character is there. Because the string is really empty, calling back() accesses an out-of-bounds element.



          You claim that your code works for $-2^63$ but you didn't add that number as a test case. I would expect it to not work since -(-2**63) is still negative.



          Besides these two issues, your code reads well and is easy to understand. Adding the additional documentation was a very good idea for everyone not fluent in Japanese.







          share|improve this answer















          share|improve this answer




          share|improve this answer








          edited Jul 29 at 5:22

























          answered Jul 29 at 5:17









          Roland IlligRoland Illig

          15.9k2 gold badges24 silver badges59 bronze badges




          15.9k2 gold badges24 silver badges59 bronze badges














          • $begingroup$
            I see. The problem is that back accesses the nonexistent element. (The terminating null character doesn't change that.)
            $endgroup$
            – L. F.
            Jul 29 at 5:22










          • $begingroup$
            @L.F. Yes, in reality most std::string implementations will have a terminating 0 byte at all times. And in fact C++11 and later requires that operator[] with pos=size() references the terminating 0. What makes back() UB is that en.cppreference.com/w/cpp/string/basic_string/back says it's UB when .empty() == true. And moreover that it's equivalent to operator[](size() - 1) which would wrap the unsigned position.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:28










          • $begingroup$
            The code definitely needs a check. Also, operator[](size() - 1) only applies if empty() is false, so wrapping is irrelevant I guess.
            $endgroup$
            – L. F.
            Jul 29 at 6:31










          • $begingroup$
            In practice g++ -O0 with libstdc++ (on Arch Linux) gives 0 when doing .back() on an empty std::string, so it doesn't help you detect this bug by crashing on that UB.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:31






          • 3




            $begingroup$
            @L.F.: fun facts: Legality of COW std::string implementation in C++11 shows how some of the new requirements in C++11 basically make efficient COW implementation of std::string impossible. With .data() also requiring a 0-terminated string, the obvious/intended implementation is to always maintain that so .data() and .c_str() can be a no-op that just returns one of the class member vars.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:36
















          • $begingroup$
            I see. The problem is that back accesses the nonexistent element. (The terminating null character doesn't change that.)
            $endgroup$
            – L. F.
            Jul 29 at 5:22










          • $begingroup$
            @L.F. Yes, in reality most std::string implementations will have a terminating 0 byte at all times. And in fact C++11 and later requires that operator[] with pos=size() references the terminating 0. What makes back() UB is that en.cppreference.com/w/cpp/string/basic_string/back says it's UB when .empty() == true. And moreover that it's equivalent to operator[](size() - 1) which would wrap the unsigned position.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:28










          • $begingroup$
            The code definitely needs a check. Also, operator[](size() - 1) only applies if empty() is false, so wrapping is irrelevant I guess.
            $endgroup$
            – L. F.
            Jul 29 at 6:31










          • $begingroup$
            In practice g++ -O0 with libstdc++ (on Arch Linux) gives 0 when doing .back() on an empty std::string, so it doesn't help you detect this bug by crashing on that UB.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:31






          • 3




            $begingroup$
            @L.F.: fun facts: Legality of COW std::string implementation in C++11 shows how some of the new requirements in C++11 basically make efficient COW implementation of std::string impossible. With .data() also requiring a 0-terminated string, the obvious/intended implementation is to always maintain that so .data() and .c_str() can be a no-op that just returns one of the class member vars.
            $endgroup$
            – Peter Cordes
            Jul 29 at 6:36















          $begingroup$
          I see. The problem is that back accesses the nonexistent element. (The terminating null character doesn't change that.)
          $endgroup$
          – L. F.
          Jul 29 at 5:22




          $begingroup$
          I see. The problem is that back accesses the nonexistent element. (The terminating null character doesn't change that.)
          $endgroup$
          – L. F.
          Jul 29 at 5:22












          $begingroup$
          @L.F. Yes, in reality most std::string implementations will have a terminating 0 byte at all times. And in fact C++11 and later requires that operator[] with pos=size() references the terminating 0. What makes back() UB is that en.cppreference.com/w/cpp/string/basic_string/back says it's UB when .empty() == true. And moreover that it's equivalent to operator[](size() - 1) which would wrap the unsigned position.
          $endgroup$
          – Peter Cordes
          Jul 29 at 6:28




          $begingroup$
          @L.F. Yes, in reality most std::string implementations will have a terminating 0 byte at all times. And in fact C++11 and later requires that operator[] with pos=size() references the terminating 0. What makes back() UB is that en.cppreference.com/w/cpp/string/basic_string/back says it's UB when .empty() == true. And moreover that it's equivalent to operator[](size() - 1) which would wrap the unsigned position.
          $endgroup$
          – Peter Cordes
          Jul 29 at 6:28












          $begingroup$
          The code definitely needs a check. Also, operator[](size() - 1) only applies if empty() is false, so wrapping is irrelevant I guess.
          $endgroup$
          – L. F.
          Jul 29 at 6:31




          $begingroup$
          The code definitely needs a check. Also, operator[](size() - 1) only applies if empty() is false, so wrapping is irrelevant I guess.
          $endgroup$
          – L. F.
          Jul 29 at 6:31












          $begingroup$
          In practice g++ -O0 with libstdc++ (on Arch Linux) gives 0 when doing .back() on an empty std::string, so it doesn't help you detect this bug by crashing on that UB.
          $endgroup$
          – Peter Cordes
          Jul 29 at 6:31




          $begingroup$
          In practice g++ -O0 with libstdc++ (on Arch Linux) gives 0 when doing .back() on an empty std::string, so it doesn't help you detect this bug by crashing on that UB.
          $endgroup$
          – Peter Cordes
          Jul 29 at 6:31




          3




          3




          $begingroup$
          @L.F.: fun facts: Legality of COW std::string implementation in C++11 shows how some of the new requirements in C++11 basically make efficient COW implementation of std::string impossible. With .data() also requiring a 0-terminated string, the obvious/intended implementation is to always maintain that so .data() and .c_str() can be a no-op that just returns one of the class member vars.
          $endgroup$
          – Peter Cordes
          Jul 29 at 6:36




          $begingroup$
          @L.F.: fun facts: Legality of COW std::string implementation in C++11 shows how some of the new requirements in C++11 basically make efficient COW implementation of std::string impossible. With .data() also requiring a 0-terminated string, the obvious/intended implementation is to always maintain that so .data() and .c_str() can be a no-op that just returns one of the class member vars.
          $endgroup$
          – Peter Cordes
          Jul 29 at 6:36













          15
















          $begingroup$

          Your magnitudes should be chou and kei (as in the supercomputer, as an aside). Also, to_Japanese() would be better named to_romaji(). As an exercise, you could try to_Japanese(number, KANJI|HIRAGANA|ROMAJI) also.



          Furthermore, it's icchou, not ichichou, and ikkei, not ichikei.






          share|improve this answer










          $endgroup$










          • 1




            $begingroup$
            Thank you for correcting my Japanese! I am a beginner and sorry for the mistakes. Regarding chou vs choo: what I learned is that when おう is a long "o", it is written as "oo" instead of "ou". I figured out that different romaji systems differ on this. And "ichichou" is so silly ;)
            $endgroup$
            – L. F.
            Jul 29 at 0:50






          • 2




            $begingroup$
            Yes, there's lots of different romaji versions - I looked up the most common Hepburn, and choo is correct, although I always use chou as it's IME-friendly, but then sennana would be typed sennnana. We're now straying into Japanese Language territory...
            $endgroup$
            – Ken Y-N
            Jul 29 at 5:59















          15
















          $begingroup$

          Your magnitudes should be chou and kei (as in the supercomputer, as an aside). Also, to_Japanese() would be better named to_romaji(). As an exercise, you could try to_Japanese(number, KANJI|HIRAGANA|ROMAJI) also.



          Furthermore, it's icchou, not ichichou, and ikkei, not ichikei.






          share|improve this answer










          $endgroup$










          • 1




            $begingroup$
            Thank you for correcting my Japanese! I am a beginner and sorry for the mistakes. Regarding chou vs choo: what I learned is that when おう is a long "o", it is written as "oo" instead of "ou". I figured out that different romaji systems differ on this. And "ichichou" is so silly ;)
            $endgroup$
            – L. F.
            Jul 29 at 0:50






          • 2




            $begingroup$
            Yes, there's lots of different romaji versions - I looked up the most common Hepburn, and choo is correct, although I always use chou as it's IME-friendly, but then sennana would be typed sennnana. We're now straying into Japanese Language territory...
            $endgroup$
            – Ken Y-N
            Jul 29 at 5:59













          15














          15










          15







          $begingroup$

          Your magnitudes should be chou and kei (as in the supercomputer, as an aside). Also, to_Japanese() would be better named to_romaji(). As an exercise, you could try to_Japanese(number, KANJI|HIRAGANA|ROMAJI) also.



          Furthermore, it's icchou, not ichichou, and ikkei, not ichikei.






          share|improve this answer










          $endgroup$



          Your magnitudes should be chou and kei (as in the supercomputer, as an aside). Also, to_Japanese() would be better named to_romaji(). As an exercise, you could try to_Japanese(number, KANJI|HIRAGANA|ROMAJI) also.



          Furthermore, it's icchou, not ichichou, and ikkei, not ichikei.







          share|improve this answer













          share|improve this answer




          share|improve this answer










          answered Jul 29 at 0:46









          Ken Y-NKen Y-N

          2591 silver badge4 bronze badges




          2591 silver badge4 bronze badges










          • 1




            $begingroup$
            Thank you for correcting my Japanese! I am a beginner and sorry for the mistakes. Regarding chou vs choo: what I learned is that when おう is a long "o", it is written as "oo" instead of "ou". I figured out that different romaji systems differ on this. And "ichichou" is so silly ;)
            $endgroup$
            – L. F.
            Jul 29 at 0:50






          • 2




            $begingroup$
            Yes, there's lots of different romaji versions - I looked up the most common Hepburn, and choo is correct, although I always use chou as it's IME-friendly, but then sennana would be typed sennnana. We're now straying into Japanese Language territory...
            $endgroup$
            – Ken Y-N
            Jul 29 at 5:59












          • 1




            $begingroup$
            Thank you for correcting my Japanese! I am a beginner and sorry for the mistakes. Regarding chou vs choo: what I learned is that when おう is a long "o", it is written as "oo" instead of "ou". I figured out that different romaji systems differ on this. And "ichichou" is so silly ;)
            $endgroup$
            – L. F.
            Jul 29 at 0:50






          • 2




            $begingroup$
            Yes, there's lots of different romaji versions - I looked up the most common Hepburn, and choo is correct, although I always use chou as it's IME-friendly, but then sennana would be typed sennnana. We're now straying into Japanese Language territory...
            $endgroup$
            – Ken Y-N
            Jul 29 at 5:59







          1




          1




          $begingroup$
          Thank you for correcting my Japanese! I am a beginner and sorry for the mistakes. Regarding chou vs choo: what I learned is that when おう is a long "o", it is written as "oo" instead of "ou". I figured out that different romaji systems differ on this. And "ichichou" is so silly ;)
          $endgroup$
          – L. F.
          Jul 29 at 0:50




          $begingroup$
          Thank you for correcting my Japanese! I am a beginner and sorry for the mistakes. Regarding chou vs choo: what I learned is that when おう is a long "o", it is written as "oo" instead of "ou". I figured out that different romaji systems differ on this. And "ichichou" is so silly ;)
          $endgroup$
          – L. F.
          Jul 29 at 0:50




          2




          2




          $begingroup$
          Yes, there's lots of different romaji versions - I looked up the most common Hepburn, and choo is correct, although I always use chou as it's IME-friendly, but then sennana would be typed sennnana. We're now straying into Japanese Language territory...
          $endgroup$
          – Ken Y-N
          Jul 29 at 5:59




          $begingroup$
          Yes, there's lots of different romaji versions - I looked up the most common Hepburn, and choo is correct, although I always use chou as it's IME-friendly, but then sennana would be typed sennnana. We're now straying into Japanese Language territory...
          $endgroup$
          – Ken Y-N
          Jul 29 at 5:59











          9
















          $begingroup$

          I think it would be better to generate the 漢字 versions of the numbers, as it's more useful in general. Make a separate class responsible for romanization (or phonetic conversion in general so it can support kana).



          Using kanji also allows for somewhat trivially adding support for formal numbers (大字), which is kind of cool/useful.



          I would also recommend adding support for breaking up the romaji sequences as reading very large numbers in romaji with no spaces is not at all fun. It could be an optional flag. A natural place to add spaces would be between magnitudes at least, or maybe between all of the various groupings you've already put together (ones, tens, hundreds, etc.).



          As for using romaji to avoid encoding issues, I recommending biting the bullet and learning how to support Unicode correctly as it will be extremely useful.






          share|improve this answer










          $endgroup$










          • 1




            $begingroup$
            Insightful. Although romanization is nontrivial AFAIK since one kanji can have multiple readings ... Spaces in between romaji is also a good idea.
            $endgroup$
            – L. F.
            Jul 29 at 3:25






          • 1




            $begingroup$
            @L.F. romanization doesn't have to support the entirety of Japanese, as this code is number focused, and you've already decided on the readings for each of the kanji involved anyway (or rather; there's only one right answer for these in this context); and that means katakana and hiragana phonetic readings are just as easy at that point.
            $endgroup$
            – briantist
            Jul 29 at 3:30















          9
















          $begingroup$

          I think it would be better to generate the 漢字 versions of the numbers, as it's more useful in general. Make a separate class responsible for romanization (or phonetic conversion in general so it can support kana).



          Using kanji also allows for somewhat trivially adding support for formal numbers (大字), which is kind of cool/useful.



          I would also recommend adding support for breaking up the romaji sequences as reading very large numbers in romaji with no spaces is not at all fun. It could be an optional flag. A natural place to add spaces would be between magnitudes at least, or maybe between all of the various groupings you've already put together (ones, tens, hundreds, etc.).



          As for using romaji to avoid encoding issues, I recommending biting the bullet and learning how to support Unicode correctly as it will be extremely useful.






          share|improve this answer










          $endgroup$










          • 1




            $begingroup$
            Insightful. Although romanization is nontrivial AFAIK since one kanji can have multiple readings ... Spaces in between romaji is also a good idea.
            $endgroup$
            – L. F.
            Jul 29 at 3:25






          • 1




            $begingroup$
            @L.F. romanization doesn't have to support the entirety of Japanese, as this code is number focused, and you've already decided on the readings for each of the kanji involved anyway (or rather; there's only one right answer for these in this context); and that means katakana and hiragana phonetic readings are just as easy at that point.
            $endgroup$
            – briantist
            Jul 29 at 3:30













          9














          9










          9







          $begingroup$

          I think it would be better to generate the 漢字 versions of the numbers, as it's more useful in general. Make a separate class responsible for romanization (or phonetic conversion in general so it can support kana).



          Using kanji also allows for somewhat trivially adding support for formal numbers (大字), which is kind of cool/useful.



          I would also recommend adding support for breaking up the romaji sequences as reading very large numbers in romaji with no spaces is not at all fun. It could be an optional flag. A natural place to add spaces would be between magnitudes at least, or maybe between all of the various groupings you've already put together (ones, tens, hundreds, etc.).



          As for using romaji to avoid encoding issues, I recommending biting the bullet and learning how to support Unicode correctly as it will be extremely useful.






          share|improve this answer










          $endgroup$



          I think it would be better to generate the 漢字 versions of the numbers, as it's more useful in general. Make a separate class responsible for romanization (or phonetic conversion in general so it can support kana).



          Using kanji also allows for somewhat trivially adding support for formal numbers (大字), which is kind of cool/useful.



          I would also recommend adding support for breaking up the romaji sequences as reading very large numbers in romaji with no spaces is not at all fun. It could be an optional flag. A natural place to add spaces would be between magnitudes at least, or maybe between all of the various groupings you've already put together (ones, tens, hundreds, etc.).



          As for using romaji to avoid encoding issues, I recommending biting the bullet and learning how to support Unicode correctly as it will be extremely useful.







          share|improve this answer













          share|improve this answer




          share|improve this answer










          answered Jul 29 at 3:12









          briantistbriantist

          1,4799 silver badges9 bronze badges




          1,4799 silver badges9 bronze badges










          • 1




            $begingroup$
            Insightful. Although romanization is nontrivial AFAIK since one kanji can have multiple readings ... Spaces in between romaji is also a good idea.
            $endgroup$
            – L. F.
            Jul 29 at 3:25






          • 1




            $begingroup$
            @L.F. romanization doesn't have to support the entirety of Japanese, as this code is number focused, and you've already decided on the readings for each of the kanji involved anyway (or rather; there's only one right answer for these in this context); and that means katakana and hiragana phonetic readings are just as easy at that point.
            $endgroup$
            – briantist
            Jul 29 at 3:30












          • 1




            $begingroup$
            Insightful. Although romanization is nontrivial AFAIK since one kanji can have multiple readings ... Spaces in between romaji is also a good idea.
            $endgroup$
            – L. F.
            Jul 29 at 3:25






          • 1




            $begingroup$
            @L.F. romanization doesn't have to support the entirety of Japanese, as this code is number focused, and you've already decided on the readings for each of the kanji involved anyway (or rather; there's only one right answer for these in this context); and that means katakana and hiragana phonetic readings are just as easy at that point.
            $endgroup$
            – briantist
            Jul 29 at 3:30







          1




          1




          $begingroup$
          Insightful. Although romanization is nontrivial AFAIK since one kanji can have multiple readings ... Spaces in between romaji is also a good idea.
          $endgroup$
          – L. F.
          Jul 29 at 3:25




          $begingroup$
          Insightful. Although romanization is nontrivial AFAIK since one kanji can have multiple readings ... Spaces in between romaji is also a good idea.
          $endgroup$
          – L. F.
          Jul 29 at 3:25




          1




          1




          $begingroup$
          @L.F. romanization doesn't have to support the entirety of Japanese, as this code is number focused, and you've already decided on the readings for each of the kanji involved anyway (or rather; there's only one right answer for these in this context); and that means katakana and hiragana phonetic readings are just as easy at that point.
          $endgroup$
          – briantist
          Jul 29 at 3:30




          $begingroup$
          @L.F. romanization doesn't have to support the entirety of Japanese, as this code is number focused, and you've already decided on the readings for each of the kanji involved anyway (or rather; there's only one right answer for these in this context); and that means katakana and hiragana phonetic readings are just as easy at that point.
          $endgroup$
          – briantist
          Jul 29 at 3:30











          7
















          $begingroup$

          I know in that in English that each word would be separate where the program is printing the all of the numbers merged together. Is this the actual functionality in Japanese?



          Since the code might be useful in many places it might be better of the translation code as in a class.



          Use of Vertical Space

          Generally code is easier to read and maintain when only one value is on a line. This would apply to the initialization of the vectors and the switch statement in the function is_vowel(). For maintenance reasons it is much easier to insert a line where it needs to be than it is to add a value to a comma separated list.



          is_vowel function

          There would be less code if the vowels were in a std::map rather than a switch statement. Here are discussions on stack overflow and software engineering.



          This portion of the answer has been modified to remove the statement that there might be a performance improvement using std::map. If map used a simple index into an array that might be true, however it is not a simple index into an array.



          Assert
          Assert statements are generally used for debugging purposes and terminate the program. Assert statements may be removed when the code is compiled without debugging as well. I don't expect to see asserts in production level code because it implies that the code is not yet debugged.






          share|improve this answer












          $endgroup$










          • 12




            $begingroup$
            "There would be less code and the performance might be better if the vowels were in a std::map rather than a switch statement." - do you have anything to support a claim that std::map is faster than a raw switch statement? Because I very much doubt that.
            $endgroup$
            – Tomáš Zato
            Jul 29 at 9:26






          • 5




            $begingroup$
            ^ Agreed with Tomas. Provide proof. std::map is dynamically-allocated, node-based, and definitely not cache friendly
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:41






          • 10




            $begingroup$
            "Assert statements are generally used for debugging purposes and throw an exception." - NO. Assert statements exist to test preconditions. Exceptions have nothing to do with preconditions. This answer is harmful.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:42







          • 7




            $begingroup$
            Failed assert()s do not throw - they terminate the program.
            $endgroup$
            – Toby Speight
            Jul 29 at 11:14






          • 6




            $begingroup$
            "It is generally better to use if statements that provide error messages rather than assert statements." - This is still severely wrong and harmful. They have completely different use cases. Assert -> precondition check, contract breakage, unrecoverable error. if statement + error -> recoverable error, can be usually handled by a human.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 13:15















          7
















          $begingroup$

          I know in that in English that each word would be separate where the program is printing the all of the numbers merged together. Is this the actual functionality in Japanese?



          Since the code might be useful in many places it might be better of the translation code as in a class.



          Use of Vertical Space

          Generally code is easier to read and maintain when only one value is on a line. This would apply to the initialization of the vectors and the switch statement in the function is_vowel(). For maintenance reasons it is much easier to insert a line where it needs to be than it is to add a value to a comma separated list.



          is_vowel function

          There would be less code if the vowels were in a std::map rather than a switch statement. Here are discussions on stack overflow and software engineering.



          This portion of the answer has been modified to remove the statement that there might be a performance improvement using std::map. If map used a simple index into an array that might be true, however it is not a simple index into an array.



          Assert
          Assert statements are generally used for debugging purposes and terminate the program. Assert statements may be removed when the code is compiled without debugging as well. I don't expect to see asserts in production level code because it implies that the code is not yet debugged.






          share|improve this answer












          $endgroup$










          • 12




            $begingroup$
            "There would be less code and the performance might be better if the vowels were in a std::map rather than a switch statement." - do you have anything to support a claim that std::map is faster than a raw switch statement? Because I very much doubt that.
            $endgroup$
            – Tomáš Zato
            Jul 29 at 9:26






          • 5




            $begingroup$
            ^ Agreed with Tomas. Provide proof. std::map is dynamically-allocated, node-based, and definitely not cache friendly
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:41






          • 10




            $begingroup$
            "Assert statements are generally used for debugging purposes and throw an exception." - NO. Assert statements exist to test preconditions. Exceptions have nothing to do with preconditions. This answer is harmful.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:42







          • 7




            $begingroup$
            Failed assert()s do not throw - they terminate the program.
            $endgroup$
            – Toby Speight
            Jul 29 at 11:14






          • 6




            $begingroup$
            "It is generally better to use if statements that provide error messages rather than assert statements." - This is still severely wrong and harmful. They have completely different use cases. Assert -> precondition check, contract breakage, unrecoverable error. if statement + error -> recoverable error, can be usually handled by a human.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 13:15













          7














          7










          7







          $begingroup$

          I know in that in English that each word would be separate where the program is printing the all of the numbers merged together. Is this the actual functionality in Japanese?



          Since the code might be useful in many places it might be better of the translation code as in a class.



          Use of Vertical Space

          Generally code is easier to read and maintain when only one value is on a line. This would apply to the initialization of the vectors and the switch statement in the function is_vowel(). For maintenance reasons it is much easier to insert a line where it needs to be than it is to add a value to a comma separated list.



          is_vowel function

          There would be less code if the vowels were in a std::map rather than a switch statement. Here are discussions on stack overflow and software engineering.



          This portion of the answer has been modified to remove the statement that there might be a performance improvement using std::map. If map used a simple index into an array that might be true, however it is not a simple index into an array.



          Assert
          Assert statements are generally used for debugging purposes and terminate the program. Assert statements may be removed when the code is compiled without debugging as well. I don't expect to see asserts in production level code because it implies that the code is not yet debugged.






          share|improve this answer












          $endgroup$



          I know in that in English that each word would be separate where the program is printing the all of the numbers merged together. Is this the actual functionality in Japanese?



          Since the code might be useful in many places it might be better of the translation code as in a class.



          Use of Vertical Space

          Generally code is easier to read and maintain when only one value is on a line. This would apply to the initialization of the vectors and the switch statement in the function is_vowel(). For maintenance reasons it is much easier to insert a line where it needs to be than it is to add a value to a comma separated list.



          is_vowel function

          There would be less code if the vowels were in a std::map rather than a switch statement. Here are discussions on stack overflow and software engineering.



          This portion of the answer has been modified to remove the statement that there might be a performance improvement using std::map. If map used a simple index into an array that might be true, however it is not a simple index into an array.



          Assert
          Assert statements are generally used for debugging purposes and terminate the program. Assert statements may be removed when the code is compiled without debugging as well. I don't expect to see asserts in production level code because it implies that the code is not yet debugged.







          share|improve this answer















          share|improve this answer




          share|improve this answer








          edited Jul 30 at 18:24

























          answered Jul 28 at 12:59









          pacmaninbwpacmaninbw

          8,9212 gold badges22 silver badges46 bronze badges




          8,9212 gold badges22 silver badges46 bronze badges










          • 12




            $begingroup$
            "There would be less code and the performance might be better if the vowels were in a std::map rather than a switch statement." - do you have anything to support a claim that std::map is faster than a raw switch statement? Because I very much doubt that.
            $endgroup$
            – Tomáš Zato
            Jul 29 at 9:26






          • 5




            $begingroup$
            ^ Agreed with Tomas. Provide proof. std::map is dynamically-allocated, node-based, and definitely not cache friendly
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:41






          • 10




            $begingroup$
            "Assert statements are generally used for debugging purposes and throw an exception." - NO. Assert statements exist to test preconditions. Exceptions have nothing to do with preconditions. This answer is harmful.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:42







          • 7




            $begingroup$
            Failed assert()s do not throw - they terminate the program.
            $endgroup$
            – Toby Speight
            Jul 29 at 11:14






          • 6




            $begingroup$
            "It is generally better to use if statements that provide error messages rather than assert statements." - This is still severely wrong and harmful. They have completely different use cases. Assert -> precondition check, contract breakage, unrecoverable error. if statement + error -> recoverable error, can be usually handled by a human.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 13:15












          • 12




            $begingroup$
            "There would be less code and the performance might be better if the vowels were in a std::map rather than a switch statement." - do you have anything to support a claim that std::map is faster than a raw switch statement? Because I very much doubt that.
            $endgroup$
            – Tomáš Zato
            Jul 29 at 9:26






          • 5




            $begingroup$
            ^ Agreed with Tomas. Provide proof. std::map is dynamically-allocated, node-based, and definitely not cache friendly
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:41






          • 10




            $begingroup$
            "Assert statements are generally used for debugging purposes and throw an exception." - NO. Assert statements exist to test preconditions. Exceptions have nothing to do with preconditions. This answer is harmful.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:42







          • 7




            $begingroup$
            Failed assert()s do not throw - they terminate the program.
            $endgroup$
            – Toby Speight
            Jul 29 at 11:14






          • 6




            $begingroup$
            "It is generally better to use if statements that provide error messages rather than assert statements." - This is still severely wrong and harmful. They have completely different use cases. Assert -> precondition check, contract breakage, unrecoverable error. if statement + error -> recoverable error, can be usually handled by a human.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 13:15







          12




          12




          $begingroup$
          "There would be less code and the performance might be better if the vowels were in a std::map rather than a switch statement." - do you have anything to support a claim that std::map is faster than a raw switch statement? Because I very much doubt that.
          $endgroup$
          – Tomáš Zato
          Jul 29 at 9:26




          $begingroup$
          "There would be less code and the performance might be better if the vowels were in a std::map rather than a switch statement." - do you have anything to support a claim that std::map is faster than a raw switch statement? Because I very much doubt that.
          $endgroup$
          – Tomáš Zato
          Jul 29 at 9:26




          5




          5




          $begingroup$
          ^ Agreed with Tomas. Provide proof. std::map is dynamically-allocated, node-based, and definitely not cache friendly
          $endgroup$
          – Vittorio Romeo
          Jul 29 at 10:41




          $begingroup$
          ^ Agreed with Tomas. Provide proof. std::map is dynamically-allocated, node-based, and definitely not cache friendly
          $endgroup$
          – Vittorio Romeo
          Jul 29 at 10:41




          10




          10




          $begingroup$
          "Assert statements are generally used for debugging purposes and throw an exception." - NO. Assert statements exist to test preconditions. Exceptions have nothing to do with preconditions. This answer is harmful.
          $endgroup$
          – Vittorio Romeo
          Jul 29 at 10:42





          $begingroup$
          "Assert statements are generally used for debugging purposes and throw an exception." - NO. Assert statements exist to test preconditions. Exceptions have nothing to do with preconditions. This answer is harmful.
          $endgroup$
          – Vittorio Romeo
          Jul 29 at 10:42





          7




          7




          $begingroup$
          Failed assert()s do not throw - they terminate the program.
          $endgroup$
          – Toby Speight
          Jul 29 at 11:14




          $begingroup$
          Failed assert()s do not throw - they terminate the program.
          $endgroup$
          – Toby Speight
          Jul 29 at 11:14




          6




          6




          $begingroup$
          "It is generally better to use if statements that provide error messages rather than assert statements." - This is still severely wrong and harmful. They have completely different use cases. Assert -> precondition check, contract breakage, unrecoverable error. if statement + error -> recoverable error, can be usually handled by a human.
          $endgroup$
          – Vittorio Romeo
          Jul 29 at 13:15




          $begingroup$
          "It is generally better to use if statements that provide error messages rather than assert statements." - This is still severely wrong and harmful. They have completely different use cases. Assert -> precondition check, contract breakage, unrecoverable error. if statement + error -> recoverable error, can be usually handled by a human.
          $endgroup$
          – Vittorio Romeo
          Jul 29 at 13:15











          4
















          $begingroup$

          You use of std::vector<std::string> for the arrays of string constants is wasteful. Both std::vector and std::string are dynamic types that can potentially allocate. A much more lightweight choice would be constexpr std::array<const char*> or constexpr std::array<std::string_view>.






          share|improve this answer










          $endgroup$














          • $begingroup$
            Fair point. string is probably not dynamic in this case due to SSO, but vector is quite wasteful.
            $endgroup$
            – L. F.
            Jul 29 at 10:42






          • 1




            $begingroup$
            Still, I like using the most minimal tool for the job whenever possible. Even if the constants are going to fit in SSO, it's good practice to use std::string_view or const char*. The compiler will also very likely be able to optimize better.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:44















          4
















          $begingroup$

          You use of std::vector<std::string> for the arrays of string constants is wasteful. Both std::vector and std::string are dynamic types that can potentially allocate. A much more lightweight choice would be constexpr std::array<const char*> or constexpr std::array<std::string_view>.






          share|improve this answer










          $endgroup$














          • $begingroup$
            Fair point. string is probably not dynamic in this case due to SSO, but vector is quite wasteful.
            $endgroup$
            – L. F.
            Jul 29 at 10:42






          • 1




            $begingroup$
            Still, I like using the most minimal tool for the job whenever possible. Even if the constants are going to fit in SSO, it's good practice to use std::string_view or const char*. The compiler will also very likely be able to optimize better.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:44













          4














          4










          4







          $begingroup$

          You use of std::vector<std::string> for the arrays of string constants is wasteful. Both std::vector and std::string are dynamic types that can potentially allocate. A much more lightweight choice would be constexpr std::array<const char*> or constexpr std::array<std::string_view>.






          share|improve this answer










          $endgroup$



          You use of std::vector<std::string> for the arrays of string constants is wasteful. Both std::vector and std::string are dynamic types that can potentially allocate. A much more lightweight choice would be constexpr std::array<const char*> or constexpr std::array<std::string_view>.







          share|improve this answer













          share|improve this answer




          share|improve this answer










          answered Jul 29 at 10:40









          Vittorio RomeoVittorio Romeo

          3051 gold badge5 silver badges21 bronze badges




          3051 gold badge5 silver badges21 bronze badges














          • $begingroup$
            Fair point. string is probably not dynamic in this case due to SSO, but vector is quite wasteful.
            $endgroup$
            – L. F.
            Jul 29 at 10:42






          • 1




            $begingroup$
            Still, I like using the most minimal tool for the job whenever possible. Even if the constants are going to fit in SSO, it's good practice to use std::string_view or const char*. The compiler will also very likely be able to optimize better.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:44
















          • $begingroup$
            Fair point. string is probably not dynamic in this case due to SSO, but vector is quite wasteful.
            $endgroup$
            – L. F.
            Jul 29 at 10:42






          • 1




            $begingroup$
            Still, I like using the most minimal tool for the job whenever possible. Even if the constants are going to fit in SSO, it's good practice to use std::string_view or const char*. The compiler will also very likely be able to optimize better.
            $endgroup$
            – Vittorio Romeo
            Jul 29 at 10:44















          $begingroup$
          Fair point. string is probably not dynamic in this case due to SSO, but vector is quite wasteful.
          $endgroup$
          – L. F.
          Jul 29 at 10:42




          $begingroup$
          Fair point. string is probably not dynamic in this case due to SSO, but vector is quite wasteful.
          $endgroup$
          – L. F.
          Jul 29 at 10:42




          1




          1




          $begingroup$
          Still, I like using the most minimal tool for the job whenever possible. Even if the constants are going to fit in SSO, it's good practice to use std::string_view or const char*. The compiler will also very likely be able to optimize better.
          $endgroup$
          – Vittorio Romeo
          Jul 29 at 10:44




          $begingroup$
          Still, I like using the most minimal tool for the job whenever possible. Even if the constants are going to fit in SSO, it's good practice to use std::string_view or const char*. The compiler will also very likely be able to optimize better.
          $endgroup$
          – Vittorio Romeo
          Jul 29 at 10:44


















          draft saved

          draft discarded















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f225082%2fjapanese-reading-of-an-integer%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown









          Popular posts from this blog

          Tamil (spriik) Luke uk diar | Nawigatjuun

          Align equal signs while including text over equalitiesAMS align: left aligned text/math plus multicolumn alignmentMultiple alignmentsAligning equations in multiple placesNumbering and aligning an equation with multiple columnsHow to align one equation with another multline equationUsing \ in environments inside the begintabularxNumber equations and preserving alignment of equal signsHow can I align equations to the left and to the right?Double equation alignment problem within align enviromentAligned within align: Why are they right-aligned?

          Where does the image of a data connector as a sharp metal spike originate from?Where does the concept of infected people turning into zombies only after death originate from?Where does the motif of a reanimated human head originate?Where did the notion that Dragons could speak originate?Where does the archetypal image of the 'Grey' alien come from?Where did the suffix '-Man' originate?Where does the notion of being injured or killed by an illusion originate?Where did the term “sophont” originate?Where does the trope of magic spells being driven by advanced technology originate from?Where did the term “the living impaired” originate?