剣指offer-面接問題11:数値の整数次方
2038 ワード
この節はやはり収穫があり,著者らはまずコードの規範性と完全性について述べた.規範性とは、明確に書くこと、明確なレイアウト、合理的な命名であり、優秀なプログラマーに対する基本的な要求でもあると思います.コードの完全性には、以前聞いたことのない概念がいくつか言及されています.コードの整合性を確保する3つの側面:機能テスト、境界テスト、負のテスト.
機能テストとは、一般的な機能のテスト例を考慮し、書かれたコードが面接官の要求を満たす基本的な機能であると同時に、問題を全面的に考慮し、漏れてはいけない.境界テスト、すなわちプログラムに再帰とループが存在する可能性があります.ループの場合、ループを終了する境界条件が正しいかどうか.再帰の場合、再帰終了の境界値が正しいかどうか.最後に、通常、負のテスト例と呼ばれる様々な可能性のあるエラー入力も考慮する.
3つのエラー処理方法:
1.戻り値.関数は呼び出し者にエラーがあるかどうかを返す値で通知します.この方法の欠陥は、戻り値が占有されているため、関数の計算結果を直接呼び出すことができません.
2.グローバル変数.この方式では,関数の計算結果を戻り値で直接呼び出すことができるが,グローバル変数のチェックを忘れやすいという欠点がある.
3.異常です.関数の実行中にエラーが発生した場合、例外を放出し、異なるエラーの原因に基づいて異なる例外タイプを定義することもできます.欠点は、一部の言語では例外がサポートされていないため、例外を投げ出すとパフォーマンスに悪影響を及ぼすことです.
次に、例として1つのトピックを示します.
関数double Power(double base,int exponent)を実現して、baseのexponentの次数を求めます.ライブラリ関数は使用できませんが、大きな数の問題を考慮する必要はありません.
最も忌み嫌うのは指数が正の整数であることだけを考慮して、指数はまた0で、負数です.指数が負数であれば、正数次べき乗を直接求めて逆数を求めればいいのですが、0は逆数を求めれないので注意が必要です.ここでは異常を返す必要があります.
2で割った代わりに右シフト演算子を用い,余剰演算子の代わりにビットと演算子を用いて1つの数が奇数であるか偶数であるかを判断した.ビット演算の効率は乗除法および余剰演算の効率よりはるかに高い.
機能テストとは、一般的な機能のテスト例を考慮し、書かれたコードが面接官の要求を満たす基本的な機能であると同時に、問題を全面的に考慮し、漏れてはいけない.境界テスト、すなわちプログラムに再帰とループが存在する可能性があります.ループの場合、ループを終了する境界条件が正しいかどうか.再帰の場合、再帰終了の境界値が正しいかどうか.最後に、通常、負のテスト例と呼ばれる様々な可能性のあるエラー入力も考慮する.
3つのエラー処理方法:
1.戻り値.関数は呼び出し者にエラーがあるかどうかを返す値で通知します.この方法の欠陥は、戻り値が占有されているため、関数の計算結果を直接呼び出すことができません.
2.グローバル変数.この方式では,関数の計算結果を戻り値で直接呼び出すことができるが,グローバル変数のチェックを忘れやすいという欠点がある.
3.異常です.関数の実行中にエラーが発生した場合、例外を放出し、異なるエラーの原因に基づいて異なる例外タイプを定義することもできます.欠点は、一部の言語では例外がサポートされていないため、例外を投げ出すとパフォーマンスに悪影響を及ぼすことです.
次に、例として1つのトピックを示します.
関数double Power(double base,int exponent)を実現して、baseのexponentの次数を求めます.ライブラリ関数は使用できませんが、大きな数の問題を考慮する必要はありません.
最も忌み嫌うのは指数が正の整数であることだけを考慮して、指数はまた0で、負数です.指数が負数であれば、正数次べき乗を直接求めて逆数を求めればいいのですが、0は逆数を求めれないので注意が必要です.ここでは異常を返す必要があります.
bool InvalidInput = false;
double PowerOfUnsignedExp(double base, int exponent)
{
if(exponent == 0)
return 1;
if(exponent == 1)
return base;
int HalfExp = exponent >> 1;
double result = PowerOfUnsignedExp(base, HalfExp);
result *= result;
if(exponent & 1 == 1)
result *= base;
return result;
}
bool equal(double num1, double num2)
{
if((num1 - num2 > -0.0000001) && (num1 - num2 < 0.0000001))
return true;
else
return false;
}
double Power(double base, int exponent)
{
if(equal(base, 0.0) && exponent < 0)
{
InvalidInput = true;
return 0.0;
}
unsigned int UnsignedExp = (unsigned int)exponent;
if(exponent < 0)
UnsignedExp = (unsigned int)(-exponent);
double result = PowerOfUnsignedExp(base, UnsignedExp);
return (exponent < 0 ? 1.0/result : result);
}
コードには、2つのテクニックが使用されています.2で割った代わりに右シフト演算子を用い,余剰演算子の代わりにビットと演算子を用いて1つの数が奇数であるか偶数であるかを判断した.ビット演算の効率は乗除法および余剰演算の効率よりはるかに高い.