main()
{int a=100,b;
float u=1.9f;
b=u*a;
printf("%d",b);
}
为什么结果是189,而不是190?
另外当u=1.7f时,或者其他的什么数字,一般都正确。
还有很多*.9这样的数字也是这样的,请问如何解决?
如果使用(int)u*a;进行转换;
我是在使用对话框中遇到这个问题的,如果用户输入一个u=1.9f,a=100,我需要在另一个文本框里显示190,如果是189,那客户岂不会把你骂死?
{int a=100,b;
float u=1.9f;
b=u*a;
printf("%d",b);
}
为什么结果是189,而不是190?
另外当u=1.7f时,或者其他的什么数字,一般都正确。
还有很多*.9这样的数字也是这样的,请问如何解决?
如果使用(int)u*a;进行转换;
我是在使用对话框中遇到这个问题的,如果用户输入一个u=1.9f,a=100,我需要在另一个文本框里显示190,如果是189,那客户岂不会把你骂死?
解决方案 »
- 如何正确调用SetLayeredWindowAttributes?
- 熟悉换肤技术的朋友请进......
- 请教高手一个关于结构体的问题
- [求助]在线求两个树控件之间的拖拽源代码
- 多张网卡的现象Mac地址和IP地址
- [VC新手系列] 关于工具条
- 高分问:一种字体的实际行高(像素)的计算方法
- 求救!高分!请问MFC怎么样使用AVIFILE类,往一个AVI文件写入多视频流!
- 【求打印预览模块的代码,只是打印预览】
- 急、急、急请问各路大仙:怎么取某函数地址并执行它?(不是DLL)分数有限,望见谅!
- 100分相送:求《VISUAL C++MFC编程实例>> 和<<VISUAL C++MFC扩展编程实例>>书的源码?[email protected]
- 动态工具条中的按钮
当你写 float u=1.9f; 时,u 里面存放的实际是1.899999999999用double就好了int main()
{
int a=100,b;
double u=1.9;
b=u*a;
printf("%d",b);
return 0;
}
{int a=100,b;
float u=1.9f;
b=(u+0.000001)*a;
printf("%d",b);
}
{int a=100,b;
float u=1.9f;
b=u*a;
printf("%d",b+0.5);
}
u+0.000001或者b=(u+0.000001)*a+0.5都可以
"%d",b+0.5是不行的。问:变为整数的时候,好象是去尾的,如何改变默认的去尾为圆整到一个最接近的整数呢?
VC6中是否可以实现?请参考http://www.dracat.net/~wyvern/papers/floatcast.pdf;
以下是引文:
Intel Float Casting
Wyvern Aldinger
One-Way Overhead
A little bit of esoteric geek-knowledge that came up recently was how fast is it to do floating point to integer
conversions in C or C++. The answer is, on an Intel anyway, expensive.
Integer to floating point is not bad. Let’s say you write the following C++ code:int i;
float f = static_cast<float>(i);This becomes just two floating-point operations: one to load an integer into a floating point register, the other to write that register back to memory. According to my assembly language reference1 this takes about17 cycles on an 80486.
The problem is in going the other way. If you naively do this in C++:
float f;
int i = static_cast<int>(f);
This becomes a whole string of assembly, often involves a function call, flushes the CPU pipeline twice, and basically has a lot of overhead.
Reason
There is so much work to converting a float into an int because of the number of ways in which it can be done. You might think of rounding a float towards zero, away from zero, towards infinity, towards negativeinfinity, or towards the nearest integer. The C specification takes the mystery out of this by defining that casting a float to an integer truncates the floating-point modulus, effectively rounding towards zero.
However, this is not the Intel hardware default.The Intel x86 Floating Point Unit (FPU) has a set of bits called the control word that determines, among other
things, rounding and truncation. By default, this control word is set to round to the nearest integer.
So when your C compiler has to do a typecast from float to int, it really involves the following steps: Read the FPU control word into a memory location
Read that memory location into a CPU register2
Modify the control word
Store the copy back into a second memory location
Load the modified control word from memory into the FPU
Store the floating point number being converted from the floating point register stack into the
destination integer in memory
Load the original control word from memory into the FPU, thus restoring the original state
That is a very large amount of work. It is not difficult to do better.1 Microsoft MASM 6.1 Reference, Microsoft Corporation, 1992.
2 There is, with one exception, no way to move data directly from the FPU registers into the CPU registers.
Refinement
Using inline assembly language in Microsoft Visual C++ 6.0, I implemented new versions of a Round() and
a Trunc() function. I then tested these against more traditional implementations of the same functions that used the compiler’s own typecasting. Tests were run both with and without compiler optimizations. After factoring out the common loop overhead, the new versions of these functions ran in about 26% of the time needed by the C cast versions.
At the loss of some accuracy, further refinement was still possible. The Intel rounding method is not quite exact in that half-integers are rounded toward zero instead of away. For instance, 0.4 and 0.5 are both rounded to 0, while 0.6 rounds to 1. If this behavior is acceptable to an application, an extra conditional can be removed from the new Round() method, yielding even better performance. I called this new version RoundFast().
Approximate running time for each function is shown below in the table.
New Functions Naïve C Functions
Trunc( ) 28% 100%
Round( ) 23% 100%
RoundFast( ) 19% -Finish
The C++ and inline assembly implementations of each function are included at the end of this document.
On a cautionary note, be aware that these new methods rely on the FPU control word being already set to do rounding rather than truncation. Since this is the default state, and as was already described most compilers will go far into the realm of ridiculous to preserve the settings, I feel this is a fairly safe assumption.
Thanks go to Jonathan Shade for pointing out this issue to me and describing the reason why it happens.
The code is my own though, so don’t hassle him with any bugs. _
Implementation
Naïve C++inline float Trunc( float x ) {
return static_cast<float>(static_cast<int>(x));
}
inline float Round( float x ) {
x = (x < 0.0) ? x-0.5f : x+0.5f;
return static_cast<float>(static_cast<int>(x));
}New Versions
// FLT_EPSILON is the smallest number on some system such that
// a + FLT_EPSILON != a
// It is defined in the header <float.h> or <cfloat>
#include <cfloat>
inline float Trunc( float x ) {
x = (x < 0.0) ? x+0.5f-FLT_EPSILON : x-0.5f+FLT_EPSILON;
int i;
_asm {
fld x
fistp i
fild i
fstp x
}
return x;
}
inline float Round( float x ) {
x = (x < 0.0f) ? x-FLT_EPSILON : x+FLT_EPSILON;
int i;
_asm {
fld x
fistp i
fild i
fstp x
}
return x;
}
inline float RoundFast( float x ) {
int i;
_asm {
fld x
fistp i
fild i
fstp x
}
return x;
}