Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ c++;,浮动到整型铸造_C++_Types_Casting - Fatal编程技术网

C++ c++;,浮动到整型铸造

C++ c++;,浮动到整型铸造,c++,types,casting,C++,Types,Casting,我只想澄清以下这些情况: #define MAP_CELL_SIZE_MIN 0.1f float mMapHeight = 256; float mScrHeight = 320; int mNumRowMax; 案例1: mNumRowMax = mMapHeight/( MAP_CELL_SIZE_MIN * mScrHeight ); mNumRowMax现在是7,但实际上它必须是8(256/32),如果我将MAP\u CELL\u SIZE\u MIN的定义更改为仅0.1,那么

我只想澄清以下这些情况:

#define MAP_CELL_SIZE_MIN 0.1f

float mMapHeight = 256;
float mScrHeight = 320;

int mNumRowMax;
案例1:

mNumRowMax = mMapHeight/( MAP_CELL_SIZE_MIN * mScrHeight );
mNumRowMax
现在是7,但实际上它必须是8(256/32),如果我将
MAP\u CELL\u SIZE\u MIN
的定义更改为仅
0.1
,那么它就变为真,
mNumRowMax
是8,那么
'f'

案例2:

float tmp = mMapHeight/( MAP_CELL_SIZE_MIN * mScrHeight );//tmp = 8.0
mNumRowMax = tmp;

mNumRowMax
现在是8,所以有人能帮我理解第一种情况下的错误吗
mNumRowMax
是7

当一个浮点数被转换为整数时,该值被截断而不是四舍五入,即所有的小数都被“截断”。看起来您遇到了四舍五入错误

一个简单的修复方法可能是使用double而不是float

如果这不是一个选项,那么您可能需要舍入到整数。例如,如果您有一个浮点值f,则执行与
intx=(int)(f+0.5)等效的操作

发生的是

5[expr] 10浮点操作数的值和浮点表达式的结果的值可以比类型要求的精度和范围更高;类型不会因此而改变。55)

55)强制转换和赋值运算符仍必须按照5.4、5.2.9和5.17中所述执行其特定转换

(C++03;C99中的6.3.1.8(2)与C11的n1570草案几乎相同;我相信C++11中的要点是相同的。)

在下面,我假设一个类似IEEE-754的二进制浮点表示

用分数十六进制表示法

1/10 = 1/2 * 3/15
     = 1/2 * 0.33333333333...
     = 2^(-4) * 1.999999999...
因此,当这四舍五入到
b
位的精度时,您得到

2^(-4) * 1.99...9a   // if b ≡ 0 (mod 4) or b ≡ 1 (mod 4)
2^(-4) * 1.99...98   // if b ≡ 2 (mod 4) or b ≡ 3 (mod 4)
其中,小数部分的最后一个十六进制数字分别在3、4、1、2最高有效位之后截断

现在
320=2^6*(2^2+1)
,因此
r*320
的结果
r
0.1
四舍五入到
b
位,是完全精确的(忽略2的幂)

b+3
位表示
b≡ 0(模块4)
b≡ 1(4型)

   6.66...60
 + 1.99...98
 -----------
   7.ff...f8
b+2
位表示
b≡ 2(模块4)
b≡ 3(mod 4)

在每种情况下,将结果四舍五入到
b
位的精度正好得到32,然后得到
256/32=8
,作为最终结果。但如果使用精度更高的中间结果,则

256/(0.1 * 320)
略小于或大于8

对于具有24(23+1)位精度的典型32位浮点
,如果中间结果以至少53位的精度表示:

0.1f = 1.99999ap-4
0.1f * 320 = 32*(1 + 2^(-26))
256/(0.1f * 320) = 8/(1 + 2^(-26)) = 8 * (1 - 2^(-26) + 2^(-52) - ...)
在案例1中,结果直接从中间结果转换为int
int
。由于中间结果略小于8,因此它被截断为7

在情况2中,中间结果在转换为
int
之前存储在
float
中,因此首先将其四舍五入到24位精度,结果正好是8位

现在,如果您去掉
f
后缀,
0.1
是一个
double
(大概有53位精度),两个
浮点
将升级为
double
,用于计算,并且

0.1 = 1.999999999999ap-4
0.1 * 320 = 32*(1 + 2^(-55))
256/(0.1 * 320) = 8 * (1 - 2^(-55) + 2^(-110) - ...)
如果以
double
精度执行计算
1+2^(-55)==1
并且已经
0.1*320==32

如果以64位或更高精度(考虑x87)的扩展精度执行计算,则文字
0.1
很可能根本不会转换为
double
精度,并直接与扩展精度一起使用,这再次导致乘法
0.1*320
的结果正好是32

如果在
double
精度下使用文字
0.1
,但在更高精度下执行计算,如果中间结果从更高精度的表示中直接截断为
int
,则再次生成7,如果在转换为
int
之前删除多余的精度,则生成8

(旁白:gcc/g++4.5.1在所有情况下都会产生8,无论优化级别如何,在我的64位机器上,我还没有在32位机器上尝试过。)


我不完全确定,但我认为这违反了标准,它应该首先去除多余的精度。有语言律师吗?

我知道该值在施法时被截断而不是四舍五入,但这个浮点值是8.0,所以截断后它仍然必须是8,而不是7@nvhausid由于浮点数的格式,计算机不能准确地表示某些数字。浮点值可能是代码> 7 99999 或打印时类似的但舍入的。<代码>数学。循环()/代码>将为您处理这个问题。@ JohnGaughan不是C或C++,只是在JavaScript中。我在想java,完全错过了C++。在标题中。似乎您可以重构此代码以使用整数并完全避免浮点。您的数学可能会有所不同(例如,除以10而不是乘以0.1),但保证精确。考虑到你的最终结果是一个整数,你有理由使用浮点吗?这篇文章只是为了说明我遇到的问题,我的实际代码是不同的,我需要使用这种形式。我现在使用0.1而不是0.1f,只是想了解可能重复的问题。我很困惑如果我从
float
转换到
int
会发生什么。因为float和int的“编码”不同,所以转换位不会直接导致值不同。像C这样的语言如何处理浮点类型转换?编辑:网站上的人建议我使用
static\u cast(floatVar)
。这是否执行了安全强制转换所需的步骤?通常,有一条机器指令用于转换,编译器只会使用它。如果没有这样的机器指令,实现(如果有这样一个不方便的平台)将
0.1 = 1.999999999999ap-4
0.1 * 320 = 32*(1 + 2^(-55))
256/(0.1 * 320) = 8 * (1 - 2^(-55) + 2^(-110) - ...)