Objective-C基元数之间的差异

时间:2022-07-13 21:30:20

What is the difference between objective-c C primitive numbers? I know what they are and how to use them (somewhat), but I'm not sure what the capabilities and uses of each one is. Could anyone clear up which ones are best for some scenarios and not others?

objective-c原始数字之间有什么区别?我知道它们是什么,以及如何使用它们(多少),但我不确定它们的功能和用途是什么。有没有人能弄清楚哪些是最适合某些场景的,而不是其他场景的?

What can I store with each one? I know that some can store more precise numbers and some can only store whole numbers. Say for example I wanted to store a latitude (possibly retrieved from a CLLocation object), which one should I use to avoid loosing any data?

我可以在每一个里面储存什么?我知道有些可以存储更精确的数字,有些只能存储整数。例如,我想存储一个纬度(可能从CLLocation对象中检索),我应该使用哪个纬度来避免丢失任何数据?

I also noticed that there are unsigned variants of each one. What does that mean and how is it different from a primitive number that is not unsigned?

我还注意到每一个都有无符号的变体。这是什么意思?它和没有无符号的原始数字有什么不同?

Apple has some interesting documentation on this, however it doesn't fully satisfy my question.

苹果在这方面有一些有趣的文档,但它并不能完全满足我的问题。

2 个解决方案

#1


4  

Well, first off types like int, float, double, long, and short are C primitives, not Objective-C. As you may be aware, Objective-C is sort of a superset of C. The Objective-C NSNumber is a wrapper class for all of these types.

首先,像int, float, double, long和short这些类型都是C原语,而不是Objective-C。如您所知,Objective-C是c的超集。Objective-C NSNumber是所有这些类型的包装类。

So I'll answer your question with respect to these C primitives, and how Objective-C interprets them. Basically, each numeric type can be placed in one of two categories: Integer Types and Floating-Point Types.

我将回答你关于C原语的问题,以及Objective-C如何解释它们。基本上,每个数字类型都可以放在两种类型中的一种:整数类型和浮点类型。


Integer Types

  • short
  • int
  • int
  • long
  • long long
  • 很久很久

These can only store, well, integers (whole numbers), and are characterized by two traits: size and signedness.

它们只能存储整数(整数),并且具有两个特征:大小和签名。

Size means how much physical memory in the computer a type requires for storage, that is, how many bytes. Technically, the exact memory allocated for each type is implementation-dependendant, but there are a few guarantees: (1) char will always be 1 byte (2) sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long).

大小意味着计算机中需要存储多少物理内存,也就是说,需要多少字节。技术上,为每种类型分配的确切内存依赖于实现,但是有一些保证:(1)char总是1字节(2)sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long) <= sizeof(long) > sizeof(long)。

Signedness means, simply whether or not the type can represent negative values. So a signed integer, or int, can represent a certain range of negative or positive numbers (traditionally –2,147,483,648 to 2,147,483,647), and an unsigned integer, or unsigned int can represent the same range of numbers, but all positive (0 to 4,294,967,295).

签名的意思是,简单地说,类型是否可以表示负值。因此,有符号整数(int)可以表示一定范围的负数或正数(传统上是-2,147,483,648到2,147,483,647),而无符号整数或无符号整数可以表示相同的数字范围,但都是正数(0到4,294,96,295)。


Floating-Point Types

  • float
  • 浮动
  • double
  • long double
  • 长两倍

These are used to store decimal values (aka fractions) and are also categorized by size. Again the only real guarantee you have is that sizeof(float) <= sizeof(double) <= sizeof (long double). Floating-point types are stored using a rather peculiar memory model that can be difficult to understand, and that I won't go into, but there is an excellent guide here.

这些用于存储十进制值(也称为分数),并且按大小分类。同样,您拥有的唯一真正的保证是sizeof(float) <= sizeof(double) <= sizeof(long double)。浮点类型是使用一种非常特殊的内存模型来存储的,这种模型很难理解,我不会深入讲解,但是这里有一个很好的指南。

There's a fantastic blog post about C primitives in an Objective-C context over at RyPress. Lots of intro CPS textbooks also have good resources.

在RyPress上有一篇关于Objective-C上下文中的C基元的很棒的博客文章。大量的CPS入门教材也有很好的资源。

#2


1  

Firstly I would like to specify the difference between au unsigned int and an int. Say that you have a very high number, and that you write a loop iterating with an unsigned int:

首先,我想指定au unsigned int和int之间的区别。假设你有一个非常高的数字,并且你写了一个循环,循环遍历一个无符号int:

for(unsigned int i=0; i< N; i++)
{ ... }

If N is a number defined with #define, it may be higher that the maximum value storable with an int instead of an unsigned int. If you overflow i will start again from zero and you'll go in an infinite loop, that's why I prefer to use an int for loops.

如果N是一个数字与# define定义,它可能是更高的最大值可储存的int,而不是一个unsigned int。如果你溢出我会重新开始从零,你就会进入一个无限循环,这就是为什么我更喜欢使用int for循环。

The same happens if for mistake you iterate with an int, comparing it to a long. If N is a long you should iterate with a long, but if N is an int you can still safely iterate with a long.

如果您使用int类型迭代,并将其与long类型进行比较,也会发生相同的情况。如果N是一个长,你应该迭代一个长,但是如果N是一个整数,你仍然可以安全地迭代一个长。

Another pitfail that may occur is when using the shift operator with an integer constant, then assigning it to an int or long. Maybe you also log sizeof(long) and you notice that it returns 8 and you don't care about portability, so you think that you wouldn't lose precision here:

另一个可能出现的缺陷是当使用带整数常数的移位操作符时,然后将其赋值为int或long。也许你也会记录sizeof(long)你会发现它返回8,你不关心可移植性,所以你认为你不会失去精度:

long i= 1 << 34;

Bit instead 1 isn't a long, so it will overflow and when you cast it to a long you have already lost precision. Instead you should type:

位1不是很长,所以它会溢出,当你将它转换为长时,你已经失去了精度。相反,你应该类型:

long i= 1l << 34;

Newer compilers will warn you about this.

更新的编译器会警告您这一点。

Taken from this question: Converting Long 64-bit Decimal to Binary.

从这个问题中得到的:将长64位的小数转换为二进制。

About float and double there is a thing to considerate: they use a mantissa and an exponent to represent the number. It's something like:

关于浮点数和双精度数有一点需要考虑:它们使用尾数和指数来表示数字。这是类似:

value= 2^exponent * mantissa

值= 2 ^指数*尾数

So the more the exponent is high, the more the floating point number doesn't have an exact representation. It may also happen that a number is too high, so that it will have a so inaccurate representation, that surprisingly if you print it you get a different number:

指数越高,浮点数就越没有精确的表示。也有可能一个数字太高了,所以它会有一个非常不准确的表示,令人惊讶的是,如果你打印它,你会得到一个不同的数字:

float f= 9876543219124567;
NSLog("%.0f",f);   // On my machine it prints 9876543585124352

If I use a double it prints 9876543219124568, and if I use a long double with the .0Lf format it prints the correct value. Always be careful when using floating points numbers, unexpected things may happen.

如果我使用double格式,它将打印9876543219124568,如果我使用长double格式和. 0lf格式,它将打印正确的值。使用浮点数时一定要小心,可能会发生意想不到的事情。

For example it may also happen that two floating point numbers have almost the same value, that you expect they have the same value but there is a subtle difference, so that the equality comparison fails. But this has been treated hundreds of times on Stack Overflow, so I will just post this link: What is the most effective way for float and double comparison?.

例如,两个浮点数的值可能是相同的,你期望它们的值是相同的,但是有细微的差别,所以相等性比较失败了。但是在Stack Overflow上已经处理了几百次了,所以我将发布这个链接:对于float和double比较,什么是最有效的方法?

#1


4  

Well, first off types like int, float, double, long, and short are C primitives, not Objective-C. As you may be aware, Objective-C is sort of a superset of C. The Objective-C NSNumber is a wrapper class for all of these types.

首先,像int, float, double, long和short这些类型都是C原语,而不是Objective-C。如您所知,Objective-C是c的超集。Objective-C NSNumber是所有这些类型的包装类。

So I'll answer your question with respect to these C primitives, and how Objective-C interprets them. Basically, each numeric type can be placed in one of two categories: Integer Types and Floating-Point Types.

我将回答你关于C原语的问题,以及Objective-C如何解释它们。基本上,每个数字类型都可以放在两种类型中的一种:整数类型和浮点类型。


Integer Types

  • short
  • int
  • int
  • long
  • long long
  • 很久很久

These can only store, well, integers (whole numbers), and are characterized by two traits: size and signedness.

它们只能存储整数(整数),并且具有两个特征:大小和签名。

Size means how much physical memory in the computer a type requires for storage, that is, how many bytes. Technically, the exact memory allocated for each type is implementation-dependendant, but there are a few guarantees: (1) char will always be 1 byte (2) sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long).

大小意味着计算机中需要存储多少物理内存,也就是说,需要多少字节。技术上,为每种类型分配的确切内存依赖于实现,但是有一些保证:(1)char总是1字节(2)sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long) <= sizeof(long) > sizeof(long)。

Signedness means, simply whether or not the type can represent negative values. So a signed integer, or int, can represent a certain range of negative or positive numbers (traditionally –2,147,483,648 to 2,147,483,647), and an unsigned integer, or unsigned int can represent the same range of numbers, but all positive (0 to 4,294,967,295).

签名的意思是,简单地说,类型是否可以表示负值。因此,有符号整数(int)可以表示一定范围的负数或正数(传统上是-2,147,483,648到2,147,483,647),而无符号整数或无符号整数可以表示相同的数字范围,但都是正数(0到4,294,96,295)。


Floating-Point Types

  • float
  • 浮动
  • double
  • long double
  • 长两倍

These are used to store decimal values (aka fractions) and are also categorized by size. Again the only real guarantee you have is that sizeof(float) <= sizeof(double) <= sizeof (long double). Floating-point types are stored using a rather peculiar memory model that can be difficult to understand, and that I won't go into, but there is an excellent guide here.

这些用于存储十进制值(也称为分数),并且按大小分类。同样,您拥有的唯一真正的保证是sizeof(float) <= sizeof(double) <= sizeof(long double)。浮点类型是使用一种非常特殊的内存模型来存储的,这种模型很难理解,我不会深入讲解,但是这里有一个很好的指南。

There's a fantastic blog post about C primitives in an Objective-C context over at RyPress. Lots of intro CPS textbooks also have good resources.

在RyPress上有一篇关于Objective-C上下文中的C基元的很棒的博客文章。大量的CPS入门教材也有很好的资源。

#2


1  

Firstly I would like to specify the difference between au unsigned int and an int. Say that you have a very high number, and that you write a loop iterating with an unsigned int:

首先,我想指定au unsigned int和int之间的区别。假设你有一个非常高的数字,并且你写了一个循环,循环遍历一个无符号int:

for(unsigned int i=0; i< N; i++)
{ ... }

If N is a number defined with #define, it may be higher that the maximum value storable with an int instead of an unsigned int. If you overflow i will start again from zero and you'll go in an infinite loop, that's why I prefer to use an int for loops.

如果N是一个数字与# define定义,它可能是更高的最大值可储存的int,而不是一个unsigned int。如果你溢出我会重新开始从零,你就会进入一个无限循环,这就是为什么我更喜欢使用int for循环。

The same happens if for mistake you iterate with an int, comparing it to a long. If N is a long you should iterate with a long, but if N is an int you can still safely iterate with a long.

如果您使用int类型迭代,并将其与long类型进行比较,也会发生相同的情况。如果N是一个长,你应该迭代一个长,但是如果N是一个整数,你仍然可以安全地迭代一个长。

Another pitfail that may occur is when using the shift operator with an integer constant, then assigning it to an int or long. Maybe you also log sizeof(long) and you notice that it returns 8 and you don't care about portability, so you think that you wouldn't lose precision here:

另一个可能出现的缺陷是当使用带整数常数的移位操作符时,然后将其赋值为int或long。也许你也会记录sizeof(long)你会发现它返回8,你不关心可移植性,所以你认为你不会失去精度:

long i= 1 << 34;

Bit instead 1 isn't a long, so it will overflow and when you cast it to a long you have already lost precision. Instead you should type:

位1不是很长,所以它会溢出,当你将它转换为长时,你已经失去了精度。相反,你应该类型:

long i= 1l << 34;

Newer compilers will warn you about this.

更新的编译器会警告您这一点。

Taken from this question: Converting Long 64-bit Decimal to Binary.

从这个问题中得到的:将长64位的小数转换为二进制。

About float and double there is a thing to considerate: they use a mantissa and an exponent to represent the number. It's something like:

关于浮点数和双精度数有一点需要考虑:它们使用尾数和指数来表示数字。这是类似:

value= 2^exponent * mantissa

值= 2 ^指数*尾数

So the more the exponent is high, the more the floating point number doesn't have an exact representation. It may also happen that a number is too high, so that it will have a so inaccurate representation, that surprisingly if you print it you get a different number:

指数越高,浮点数就越没有精确的表示。也有可能一个数字太高了,所以它会有一个非常不准确的表示,令人惊讶的是,如果你打印它,你会得到一个不同的数字:

float f= 9876543219124567;
NSLog("%.0f",f);   // On my machine it prints 9876543585124352

If I use a double it prints 9876543219124568, and if I use a long double with the .0Lf format it prints the correct value. Always be careful when using floating points numbers, unexpected things may happen.

如果我使用double格式,它将打印9876543219124568,如果我使用长double格式和. 0lf格式,它将打印正确的值。使用浮点数时一定要小心,可能会发生意想不到的事情。

For example it may also happen that two floating point numbers have almost the same value, that you expect they have the same value but there is a subtle difference, so that the equality comparison fails. But this has been treated hundreds of times on Stack Overflow, so I will just post this link: What is the most effective way for float and double comparison?.

例如,两个浮点数的值可能是相同的,你期望它们的值是相同的,但是有细微的差别,所以相等性比较失败了。但是在Stack Overflow上已经处理了几百次了,所以我将发布这个链接:对于float和double比较,什么是最有效的方法?