我刚刚听说iphone不能原生地加倍,从而使它们比常规漂浮慢得多.
这是真的?证据?
我对这个问题很感兴趣,因为我的程序需要高精度计算,而且我必须在速度上妥协.
我一直在阅读很多关于.NET中浮点确定性的内容,即确保具有相同输入的相同代码将在不同的机器上提供相同的结果.由于.NET缺少Java的fpstrict和MSVC的fp:strict等选项,因此似乎一致认为使用纯托管代码无法绕过这个问题.C#游戏AI Wars已经决定使用定点数学,但这是一个麻烦的解决方案.
主要问题似乎是CLR允许中间结果存在于FPU寄存器中,这些寄存器具有比类型的原始精度更高的精度,从而导致不可预测的更高精度结果.CLR工程师David Notario撰写的MSDN文章解释了以下内容:
请注意,对于当前规范,它仍然是提供"可预测性"的语言选择.在每次FP操作之后,该语言可以插入conv.r4或conv.r8指令以获得"可预测的"行为. 显然,这非常昂贵,不同的语言有不同的妥协.例如,C#什么都不做,如果你想缩小,你必须手动插入(浮点)和(双)强制转换.
这表明,只需为每个表达式和计算浮点数的子表达式插入显式强制转换,就可以实现浮点确定性.有人可能会在float周围编写一个包装器类型来自动执行此任务.这将是一个简单而理想的解决方案!
然而,其他评论表明它并非如此简单.Eric Lippert最近表示(强调我的):
在某些版本的运行时中,显式转换为float会产生与不这样做不同的结果.当你明确地转换为float时,C#编译器会给运行时提供一个提示,说"如果碰巧使用这个优化,就把这个东西从超高精度模式中取出".
这对运行时的"提示"是什么?C#规范是否规定显式转换为float会导致在IL中插入conv.r4?CLR规范是否规定conv.r4指令会使值缩小到其原始大小?只有当这两者都成立时,我们才能依靠显式转换来提供浮点"可预测性",正如David Notario所解释的那样.
最后,即使我们确实能够将所有中间结果强制转换为类型的原生大小,这是否足以保证跨机器的可重复性,还是有其他因素如FPU/SSE运行时设置?
C++标准没有讨论float和double类型的底层布局,只讨论它们应该表示的值的范围.(对于签名类型也是如此,这是两个恭维还是别的)
我的问题是:用于以可移植方式序列化/反序列化POD类型(如double和float)的技术是什么?目前,似乎唯一的方法是将值表示为字面意义(如"123.456"),double的ieee754布局在所有体系结构上都不是标准的.
我可以知道Double.MIN_NORMAL(在1.6中引入)和Double.MIN_VALUE之间的区别是什么?
JavaDoc Double.MIN_NORMAL
:
保持类型最小正正常值的常数
Double.MIN_VALUE
,2 -1022
JavaDoc Double.MIN_NORMAL
:
保持最小正非零值类型的常量
Double.MIN_VALUE
,2 -1074
我对IEEE-754浮点比较规则的理解是,!=
如果其中一个或两个参数都是NaN,则所有比较运算符将返回false,而!=
运算符将返回true.我可以通过简单的独立测试轻松重现此行为:
for (int ii = 0; ii < 4; ++ii)
{
float a = (ii & 1) != 0 ? NAN : 1.0f;
float b = (ii & 2) != 0 ? NAN : 2.0f;
#define TEST(OP) printf("%4.1f %2s %4.1f => %s\n", a, #OP, b, a OP b ? "true" : "false");
TEST(<)
TEST(>)
TEST(<=)
TEST(>=)
TEST(==)
TEST(!=)
}
Run Code Online (Sandbox Code Playgroud)
这将打印预期结果:(NaN的格式-1.$
与MSVC运行时一样)
1.0 < 2.0 => true
1.0 > 2.0 => false
1.0 <= 2.0 => …
Run Code Online (Sandbox Code Playgroud) 我有关于如何从基数10转换为IEEE 754浮点表示的示例
Number: 45.25 (base 10) = 101101.01 (base 2) Sign: 0
Normalized form N = 1.0110101 * 2^5
Exponent esp = 5 E = 5 + 127 = 132 (base 10) = 10000100 (base 2)
IEEE 754: 0 10000100 01101010000000000000000
Run Code Online (Sandbox Code Playgroud)
除了一段之外,这对我有意义:
45.25 (base 10) = 101101.01 (base 2)
Run Code Online (Sandbox Code Playgroud)
45是二进制的101101,没关系..但他们是如何获得0.25的.01?
考虑以下代码,这是我实际问题的SSCCE:
#include <iostream>
int roundtrip(int x)
{
return int(float(x));
}
int main()
{
int a = 2147483583;
int b = 2147483584;
std::cout << a << " -> " << roundtrip(a) << '\n';
std::cout << b << " -> " << roundtrip(b) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
我的电脑(Xubuntu 12.04.3 LTS)上的输出是:
2147483583 -> 2147483520
2147483584 -> -2147483648
Run Code Online (Sandbox Code Playgroud)
请注意b
往返后正数如何变为负数.这种行为是否明确规定?我原本期望int-to-float round-tripping至少能正确保存符号......
嗯,在ideone上,输出是不同的:
2147483583 -> 2147483520
2147483584 -> 2147483647
Run Code Online (Sandbox Code Playgroud)
g ++团队是否在此期间修复了错误,或者两个输出都完全有效?
ECMAScript 6 Number.MAX_SAFE_INTEGER
应该代表JavaScript在浮点精度出现问题之前可以存储的最大数值.但是,要求添加到此值的数字1也必须表示为a Number
.
Number.MAX_SAFE_INTEGER
注意值
Number.MAX_SAFE_INTEGER
是最大的整数n
,n
并且n + 1
可以完全表示为Number
值.价值
Number.MAX_SAFE_INTEGER
是9007199254740991 (2^53?1)
.
Chrome,Firefox,Opera和IE11的JavaScript控制台都可以安全地执行9,007,199,254,740,992的计算.一些测试:
// Valid
Math.pow(2, 53) // 9007199254740992
9007199254740991 + 1 // 9007199254740992
9007199254740992 - 1 // 9007199254740991
9007199254740992 / 2 // 4503599627370496
4503599627370496 * 2 // 9007199254740992
parseInt('20000000000000', 16) // 9007199254740992
parseInt('80000000000', 32) // 9007199254740992
9007199254740992 - 9007199254740992 // 0
9007199254740992 == 9007199254740991 // false
9007199254740992 == 9007199254740992 // true
// Erroneous …
Run Code Online (Sandbox Code Playgroud) 我只是好奇,为什么在IEEE-754
任何非零浮点数除以零时会产生无穷大的值?从数学角度来看,这是无稽之谈.所以我认为这个操作的正确结果是NaN.
如果x是实数,则当x = 0时,不定义函数f(x)= 1/x.例如,如果IEEE-754
生成NaN
值,则不为任何负数定义函数sqrt,并为sqrt(-1.0f)定义函数sqrt .但1.0f/0是Inf
.
但由于某些原因,事实并非如此IEEE-754
.必须有一个原因,可能是一些优化或兼容性原因.
那有什么意义呢?
似乎IEEE 754标准将16,777,214个32位浮点值定义为NaN,或所有可能值的0.4%.
我想知道保留这么多有用值的理由是什么,而基本上只需要2个:一个用于信令,一个用于安静的NaN.
对不起,如果这个问题很简单,我在互联网上找不到任何解释.
ieee-754 ×10
c++ ×4
c ×2
nan ×2
.net ×1
c# ×1
cocoa-touch ×1
double ×1
ecmascript-6 ×1
integer ×1
iphone ×1
java ×1
javascript ×1
portability ×1