18

C、C ++にはdivという関数があります(stdlib.h)

div_t div(int numer, int denom);

typedef struct _div_t
{
  int quot;
  int rem;
} div_t;

ただし、C、C ++には/および%演算子があります。

私の質問は、「/および%演算子がある場合、div関数は役に立ちますか?」です。

4

6 に答える 6

17

はい、そうです。1回の操作で商と剰余を計算します。

それを除けば、同じ動作を/+で実現できます(そして、まともなオプティマイザーはとにかく%それらを単一に最適化します)。div

要約すると、パフォーマンスの最後のビットを絞り出すことに関心がある場合、特にプラットフォームのオプティマイザーがそれほど高度でない場合は、これが選択できる機能になる可能性があります。これは、組み込みプラットフォームの場合によくあります。それ以外の場合は、読みやすい方法を使用してください。

于 2011-07-16T15:10:53.177 に答える
13

div()関数は、最初のパラメーター(分子)と2番目のパラメーター(分母)の除算の商と余りを含む構造体を返します。4つのバリエーションがあります。

  1. div_t div(int, int)
  2. ldiv_t ldiv(long, long)
  3. lldiv_t lldiv(long long, long long)
  4. imaxdiv_t imaxdiv(intmax_t, intmax_t(intmax_tは、システムで使用可能な最大の整数型を表します)

構造は次のdiv_tようになります。

typedef struct
  {
    int quot;           /* Quotient.  */
    int rem;            /* Remainder.  */
  } div_t;

実装は単に/and%演算子を使用するため、それほど複雑または必要な関数ではありませんが、C標準の一部です([ISO 9899:201x] [1]で定義されています)。

GNUlibcの実装を参照してください。

/* Return the `div_t' representation of NUMER over DENOM.  */
div_t
div (numer, denom)
     int numer, denom;
{
  div_t result;

  result.quot = numer / denom;
  result.rem = numer % denom;

  /* The ANSI standard says that |QUOT| <= |NUMER / DENOM|, where
     NUMER / DENOM is to be computed in infinite precision.  In
     other words, we should always truncate the quotient towards
     zero, never -infinity.  Machine division and remainer may
     work either way when one or both of NUMER or DENOM is
     negative.  If only one is negative and QUOT has been
     truncated towards -infinity, REM will have the same sign as
     DENOM and the opposite sign of NUMER; if both are negative
     and QUOT has been truncated towards -infinity, REM will be
     positive (will have the opposite sign of NUMER).  These are
     considered `wrong'.  If both are NUM and DENOM are positive,
     RESULT will always be positive.  This all boils down to: if
     NUMER >= 0, but REM < 0, we got the wrong answer.  In that
     case, to get the right answer, add 1 to QUOT and subtract
     DENOM from REM.  */

  if (numer >= 0 && result.rem < 0)
    {
      ++result.quot;
      result.rem -= denom;
    }

  return result;
}
于 2011-07-16T16:07:20.763 に答える
10

div()のセマンティクスは、%および/のセマンティクスとは異なります。これは、場合によっては重要です。そのため、psYchoticの回答に示されている実装に次のコードが含まれています。

if (numer >= 0 && result.rem < 0)
    {
      ++result.quot;
      result.rem -= denom;
    }

%は負の答えを返す場合がありますが、div()は常に負でない余りを返します。

WikiPediaのエントリを確認してください。特に、「負の数の丸めが実装に依存するCの通常の整数除算とは異なり、divは常に0に向かって丸められます。」

于 2011-07-16T16:26:40.117 に答える
7

div()C99以前のニーズを満たす:移植性

C99より前では、負のオペランドを持つ商の丸め方向a / bは実装に依存していました。を使用div()すると、丸め方向はオプションではありませんが、0に向かって 指定さdiv()れます。均一なポータブル除算が提供されます。二的な用途は、コードが商と剰余の両方を計算する必要がある場合の潜在的な効率でした。

C99以降では、同じラウンド方向div()を指定し、より優れたコンパイラーが近くのコードを/最適化することで、必要性が減少しました。a/ba%b


これが説得力のある理由でdiv() あり、C仕様にないことを説明しています。負のオペランドを使用しudiv_t udiv(unsigned numer, unsigned denom)た実装に依存する結果の問題は、C99より前でもa/b存在しません。unsigned

于 2014-09-08T22:39:23.693 に答える
1

おそらく、多くのプロセッサではdiv命令が両方の値を生成し、同じ入力の隣接する/および%演算子が1つの操作に合体される可能性があることを常にコンパイラに期待できるためです。

于 2011-07-16T15:13:09.870 に答える
0

両方の価値が必要な場合は、より少ない時間で済みます。CPUは、除算を実行するときに常に余りと商の両方を計算します。「/」を1回使用し、「%」を1回使用すると、CPUは両方の数値を2回計算します。

(私の貧弱な英語を許してください、私はネイティブではありません)

于 2011-07-16T15:12:21.120 に答える