web-dev-qa-db-ja.com

CGFloatを丸める方法

私はこの方法を作りました

+ (CGFloat) round: (CGFloat)f {
    int a = f;
    CGFloat b = a;
    return b;
}

期待どおりに機能しますが、切り捨てられるだけです。そして、それが負の数である場合でも、切り捨てられます。

これは私が作成した簡単な方法でした。正しく丸めることはそれほど重要ではありません。ゲームのカメラのx値とy値を丸めるだけです。

この方法は大丈夫ですか?速いですか?それとももっと良い解決策はありますか?

19
Johannes Jensen

<math.h>には、floorfceilfroundfrintfnearbyintf(lasf'f 'は「float」バージョンを意味し、それがないバージョンは「double」バージョンです)。

標準的な方法だけでなく、Edgeの場合にうまく機能するため、標準的な方法を使用することをお勧めします。

2013アップデート(jessedc)

iOSはもはや32ビットだけではありません。この質問に対する他の多くの回答があり、現在はより関連性があります。

ほとんどの回答は、tgmath.hのインポートについて言及しています。

26
SergGr

2018回答

ここでの他の回答は、日付が付けられているか、良い例を示していません。 Swiftに組み込まれているCGFloat関数を使用すると、roundedを簡単に丸めることができます。

_let x: CGFloat = 3.5
let y = x.rounded() // 4.0
_

値をその場で丸めたい場合は、roundを使用できます。

_var x: CGFloat = 3.5
x.round() // 4.0
_

丸め規則

数値の丸め方をより正確に制御したい場合は、 FloatingPointRoundingRule を使用できます。

ゼロから離れて

_x.rounded(.awayFromZero)
_

ゼロより上の数値は切り上げられ、ゼロより下の数値は切り捨てられます。

_3.000  ->  3.0
3.001  ->  4.0
3.499  ->  4.0
3.500  ->  4.0
3.999  ->  4.0

-3.000  ->  -3.0
-3.001  ->  -4.0
-3.499  ->  -4.0
-3.500  ->  -4.0
-3.999  ->  -4.0
_

ダウン

_x.rounded(.down)
_

10進数の数値は、次に小さい整数に切り捨てられます。これはfloor(x)と同じです。

_3.000  ->  3.0
3.001  ->  3.0
3.499  ->  3.0
3.500  ->  3.0
3.999  ->  3.0

-3.000  ->  -3.0
-3.001  ->  -4.0
-3.499  ->  -4.0
-3.500  ->  -4.0
-3.999  ->  -4.0
_

ゼロに最も近いまたはゼロから離れる

_x.rounded(.toNearestOrAwayFromZero)   // same as x.rounded()
_

10進数は、最も近い整数値に丸められます。ただし、値がちょうど真ん中にある場合(_3.5_または_-3.5_など)、正の数は切り上げられ、負の数は切り捨てられます。

それは長く複雑な名前を持っているかもしれませんが、これは通常、学校で丸めを学ぶ方法です。これは、x.rounded()を実行する場合に使用されるルールでもあります。

_3.000  ->  3.0
3.001  ->  3.0
3.499  ->  3.0
3.500  ->  4.0  ***
3.999  ->  4.0

-3.000  ->  -3.0
-3.001  ->  -3.0
-3.499  ->  -3.0
-3.500  ->  -4.0  ***
-3.999  ->  -4.0
_

最も近いまたは偶数に

_x.rounded(.toNearestOrEven)
_

これはtoNearestOrAwayFromZeroに似ていますが、_.5_値が偶数の整数に丸められる点が異なります。

_3.000  ->  3.0
3.001  ->  3.0
3.499  ->  3.0
3.500  ->  4.0   ***
3.999  ->  4.0
4.500  ->  4.0   ***

-3.000  ->  -3.0
-3.001  ->  -3.0
-3.499  ->  -3.0
-3.500  ->  -4.0   ***
-3.999  ->  -4.0
-4.500  ->  -4.0   ***
_

ゼロに向かって

_x.rounded(.towardZero)
_

これには、10進値を切り捨てる効果があります。 Intが必要な場合は、Int(x)でも同じことができます。

_3.000  ->  3.0
3.001  ->  3.0
3.499  ->  3.0
3.500  ->  3.0
3.999  ->  3.0

-3.000  ->  -3.0
-3.001  ->  -3.0
-3.499  ->  -3.0
-3.500  ->  -3.0
-3.999  ->  -3.0
_

_x.rounded(.up)
_

これは_.down_の反対です。 10進数はすべて切り上げられます。これはceil(x)と同じです。

_3.000  ->  3.0
3.001  ->  4.0
3.499  ->  4.0
3.500  ->  4.0
3.999  ->  4.0

-3.000  ->  -3.0
-3.001  ->  -3.0
-3.499  ->  -3.0
-3.500  ->  -3.0
-3.999  ->  -3.0
_

ノート

  • 負の値を考慮することを忘れないでください。
  • roundroundedの結果はまだCGFloatです。 Intが必要な場合は、Int(myCGFloat)のように変換する必要があります。
  • C数学関数round(x)ceil(x)、およびfloor(x)を使用する必要はもうありません。ただし、それらを使用する場合は、64ビットアーキテクチャと32ビットアーキテクチャの両方を処理するため、roundfceilf、およびfloorfで見た回答はすべて廃止されています。
51
Suragch

CGFloatdoubleまたはfloatのいずれかにtypedefされるため、他の実際の型と同じように丸めることができます。

CGFloat round(CGFloat aFloat)
{
    return (int)(aFloat + 0.5);
}

これは、端数を運ぶのに十分小さいフロートでは機能しますが、大きな値では奇妙に動作する可能性があることに注意してください。

5
zneak

#import "tgmath.h"をお試しください。

<tgmath.h>ヘッダーには、ヘッダー<math.h>および<complex.h>が含まれ、いくつかの型ジェネリックマクロを定義します。

1
Mikhail

32ビットおよび64ビットで作業する場合は、次のような独自のマクロを作成できます。

#ifndef CGFLOAT_CEIL
    #ifdef CGFLOAT_IS_DOUBLE
        #define CGFLOAT_CEIL(value) ceil(value)
    #else
        #define CGFLOAT_CEIL(value) ceilf(value)
    #endif
#endif

PSこれは質問に対する答えではなく、32/64ビット値の操作方法に関する質問への追加です。

MyMacros.hのようなファイルでこれを定義し、myapp-Prefix.pchにインポートを追加します

また、関数のプレフィックスとしてCGFloatを選択すると、リスクが生じる可能性があることにも注意してください。Appleは、このようなマクロを自分で追加する可能性があるため、#ifndefCGFLOAT_CEILは

0
Saren Inden

あなたは車輪の再発明をしています-これはCの質問であり、Objective Cではありません。標準のCのround()関数を使用するだけです。

0
Paul Lynch