1

左方向の小数または基数に依存しない整数を切り捨てるエレガントな方法はありますか?

たとえば、私は持っています:

unsigned int val1 = 17301;

アルゴリズムは、1 回の呼び出しで左から 1 (10 進数) 桁を切り捨てる必要があるため、val1 の場合、4 回の呼び出しの結果は次のようになります。

truncate_left(17301) returns 7301
truncate_left(7301) returns 301
truncate_left(301) returns 1
truncate_left(1) returns 0

戻り値も整数です。私には c/c++ ソリューションが最適です。外部の(および/または)数学ライブラリは歓迎されません。それを行う一般的な方法に興味があります

@ATaylor私の醜い解決策は次のとおりです。

unsigned int truncate_left(unsigned int val) {
  unsigned int divider = 1000000000, dec;
  for(unsigned int pow10 = 10; pow10 > 0; pow10--) {
    if(val % divider != val) {
      dec = val / divider;
      printf("dec = %d\n", divider);
      break;
    }
    divider /= 10;
  }
  return val - dec * divider;
}

ありがとう!

4

7 に答える 7

5

なぜ@MMが彼のほぼそこにある回答を削除したのかはわかりませんが、修正されたバージョンは次のとおりです。

int truncate_left(int x)
{
    int c = (int)log10(x);
    while (x > pow(10,c)) x -= pow(10,c);
    return x;
}

math.h と -lm の使用が問題になる場合は、log10 と pow を次のように置き換えます。

int mylog10(int val)
{
   if (val > 9) return 1 + mylog10(val/10);
   return 1;
}

int mypow(int val, int pwr)
{
    if (pwr > 0) return val * mypow(val, pwr-1);
    return val;
}
于 2013-04-23T11:38:07.343 に答える
3

これはちょっとした回避策ですが、あなたが望むようにする必要があります(なぜあなたがそれを望んでいるのかわかりませんが)

とにかく、まず最初に、どの数字が一番左の数字かを判断する必要があります。

このためには、基数を知る必要があります (知っていますよね?) 一番左の桁がわかったら、この正確な桁を基数倍の位置で減算する必要があります...これで完了です。

これを行う方法に関するコードの断片を次に示します。未テストですが。

int truncate_left(int val, int base) {    
    int Multiplier = 1, LeftDigit = val;
    while(LeftDigit > base) {
        LeftDigit /= base;
        Multiplier *= base;
    }
    return val - (LeftDigit * Multiplier);
}

負の数も扱うには、少し追加する必要があります。

int truncate_left(int val, int base) {
    bool isNegative = (val < 0);
    int Multiplier = 1, LeftDigit = val;
    if(isNegative) LeftDigit *= -1;
    while(LeftDigit > base) {
        LeftDigit /= base;
        Multiplier *= base;
    }
    if(isNegative) LeftDigit *= -1;
    return val - (LeftDigit * Multiplier);
}

数値が最初から負で、便宜上存在する場合、isNegativeフラグは記憶します (2 回チェックすることもできますval < 0)。それはLeftDigit正に変わります(これは「絶対値」であり、乗数を決定してから負に戻します。

は負であり、valそこから別の負の値を減算すると (-LeftDigit * Multiplier)、合計は に+なり、符号が保持された正しい結果が得られます。

于 2013-04-23T11:34:23.063 に答える
3

文字列がごまかしていない場合:

int truncate_left(int i) {
    return std::stoi(std::to_string(i).substr(1));
}
于 2013-04-23T11:38:42.050 に答える
2

手っ取り早い方法はありません。17301 を 10000 + 7301 と書く必要があります。truncate_left が 7301 の部分を返すことは明らかです。これで、10000 の部分を理解することができます。これは、「数字を出力する」コード例からニックネームを付けることができます。

于 2013-04-23T11:35:18.347 に答える
1

こちらもチェックして、

unsigned int tru(unsigned int a)
{
unsigned int b = a,c=0;

while(b!=0)
{
 c++;
 b /=10;
}

cout<<"length: "<<c<<endl;

int mul= 1;
c--;

while(c)
{
 mul *= 10;
 c--;
}

cout<<"mul is "<<mul<<endl;

return a%mul;
}
于 2013-04-23T12:02:54.933 に答える
1
unsigned truncate_left_aux(unsigned n, unsigned sum, unsigned base){
    unsigned nn;
    return (0==(nn=n/10))? sum : truncate_left_aux(nn, sum + (n % 10) * base, 10*base);
}

unsigned truncate_left(unsigned n){
    truncate_left_aux(n, 0, 1);
}
于 2013-04-23T12:08:50.600 に答える