问题标签 [single-precision]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 用 4 个复合字节构建一个 32 位浮点数
我正在尝试用它的 4 个复合字节构建一个 32 位浮点数。有没有比使用以下方法更好(或更便携)的方法来做到这一点?
c# - 在 64 位机器上运行 x86 编译代码时单精度算术中断
当您阅读MSDN 时System.Single
:
Single
符合二进制浮点运算的 IEC 60559:1989 (IEEE 754) 标准。
和 C# 语言规范:
和类型使用 32 位单精度
float
和double
64 位双精度 IEEE 754 格式表示 [...]
然后:
该乘积是根据 IEEE 754 算术规则计算的。
float
您很容易得到类型及其乘法符合 IEEE 754的印象。
乘法是明确定义的,这是 IEEE 754 的一部分。我的意思是当你有两个float
实例时,只有一个float
是他们的“正确”产品。不允许产品依赖于计算它的系统的某些“状态”或“设置”。
现在,考虑以下简单程序:
除了编写一些环境信息和编译配置外,程序只考虑两个float
s(即a
和b
)及其乘积。最后四行是有趣的。以下是使用Debug x86(左)、Release x86(中)和x64(右)编译后在 64 位机器上运行的输出:
我们得出结论,简单float
操作的结果取决于构建配置。
之后的第一行是对两个s"case .58"
的简单检查。float
我们希望它独立于构建模式,但事实并非如此。我们希望接下来的两行是相同的,因为它不会改变任何将 afloat
转换为 a 的内容float
。但他们不是。我们也希望他们能够阅读"True↩ True"
,因为我们正在将产品a*b
与自身进行比较。我们期望输出的最后一行独立于构建配置,但事实并非如此。
为了弄清楚正确的产品是什么,我们手动计算。0.58
( )的二进制表示a
为:
其中括号中的块是永远重复的周期。这个数字的单精度表示需要四舍五入为:
我们已经四舍五入(在本例中向下舍入)到最接近的可表示的Single
. 现在,数字“一百”(b
)是:
在二进制。计算数字的完整乘积(*)
并(**)
给出:
四舍五入(在这种情况下向上舍入)到单精度给出
我们四舍五入的地方是因为下一位是1
,而不是0
(四舍五入到最接近的)。所以我们得出结论,结果是58f
根据 IEEE 的。根据 IEEE,这不是以任何方式先验给出的,例如0.59f * 100f
小于59f
和0.60f * 100f
大于。60f
所以看起来 x64 版本的代码是正确的(上图中最右边的输出窗口)。
注意:如果这个问题的任何读者有一个旧的 32 位 CPU,听听上面程序在他们的架构上的输出会很有趣。
现在的问题:
- 以上是bug吗?
- 如果这不是一个错误,那么C# 规范中的哪个位置说运行时可以选择执行
float
具有额外精度的乘法然后“忘记”以再次摆脱该精度? - 将
float
表达式转换为类型如何float
改变任何东西? (a*b)
当它们在数学上(根据 IEEE)应该是等效的(根据 IEEE)时,看似无辜的操作(例如通过将一个拉出到一个临时局部变量)将一个表达式拆分为两个表达式会改变行为,这难道不是一个问题吗?程序员如何提前知道运行时是否选择保持float
“人工”额外(64 位)精度?- 为什么允许在发布模式下编译的“优化”改变算术?
(这是在 .NET Framework 的 4.0 版本中完成的。)
c - C如何知道期望什么类型?
如果所有值都只是一个或多个字节,并且没有一个字节可以包含元数据,那么系统如何跟踪一个字节代表的数字类型?在 Wikipedia 上查看 Two's Complement 和 Single Point 揭示了这些数字如何以基数 2 表示,但我仍然想知道编译器或处理器(不确定我在这里真正处理的是哪个)确定这个字节必须是一个有符号整数。
这类似于收到一封加密的信件,然后看着我的密码书架,想知道该拿哪一个。一些指标是必要的。
如果我考虑我可以做些什么来解决这个问题,我会想到两个解决方案。要么我会要求一个额外的字节并用它来存储描述,要么我会专门为数字表示分配内存部分;有符号数的部分,浮点数的部分等。
我主要在 Unix 系统上处理 C,但这可能是一个更普遍的问题。
floating-point - c_k 的准确度 = a + ( N + k ) * b
a, b 为 32 位浮点值,N 为 32 位整数,k 可以取值 0, 1, 2, ... M。需要计算 c_k = a + ( N + k ) * b; 这些操作需要是 32 位操作(不是双精度)。关注的是准确性——以下哪个更准确?:
I) c_k = a + ( N + k ) * b
II)首先计算:c_0 = a + N * b
然后通过加法迭代计算c_1,c_2等:
c_1 = c_0 + b;
c_2 = c_1 + b;
types - Why IEEE754 single-precision float has only 7 digit precision?
Why does a single-precision floating point number have 7 digit precision (or double 15-16 digits precision)?
Can anyone please explain how we arrive on that based on the 32 bits assigned for float(Sign(32) Exponent(30-23), Fraction (22-0))?
floating-point - MIPS - 如何将一组整数转换为单精度浮点数
我真的很难弄清楚如何解决这个问题。我知道我想采用整数和小数的二进制表示,将它们组合为尾数,并将符号位分配给开头,但我不知道如何在 MIPS 中实际实现它。
任何人都可以帮助我至少开始吗?
假设您的 MIPS 硬件没有浮点寄存器和浮点 ALU。如果要执行浮点加法,则必须使用使用整数寄存器 ($0 - $31) 和整数 ALU 的 MIPS 整数指令来完成工作。在这个赋值问题中,您将编写 MIPS 代码,仅使用整数指令和整数寄存器,来实现一个将两个浮点数相加的过程,并编写一个 main 函数来调用该过程。
编写 MIPS 过程 toFloat 以将浮点数转换为 IEEE 单精度格式。该过程以三个整数为输入:$a0、$a1、$a2,分别代表一个浮点数:如果 $a0 包含 0,则浮点数为正数,否则如果 $a0 包含 1,则浮点数为负数。寄存器$a1 中存储的数字是浮点数的整数部分,寄存器$a2 中存储的数字是浮点数的小数部分。例如,要显示浮点数 -5.25,三个输入寄存器应包含以下数字:$a0 = 1、$a1 = 5 和 $a2 = 25。对于小数部分,您可以使用 div rs rt将 25 除以 100 的指令. 分数将存储在 HI 寄存器中,您可以使用 mfhi 指令检索分数。该过程将返回 v0,其中包含对应于由三个输入数字表示的浮点数的 IEEE 单精度模式。完成此过程后,您可以使用它将输入数字 2.5 和 7.5 转换为其 IEEE 单精度格式。
编写 MIPS 过程printFloat以打印 IEEE 单精度格式的数字。过程的输入是 $a0,它是一个 IEEE 单精度格式的数字。该过程将简单地打印存储在 $a0 中的位模式。您可以使用循环打印每个位。完成此过程后,您可以使用它以浮点格式打印输入数字2.5和7.5 。
编写一个 MIPS 程序来实现 main 函数来调用你的程序。在这个程序中,您将调用
toFloat(0, 2, 5) 生成 2.5 的浮点格式;
toFloat(0, 7, 5) 生成 7.5 的浮点格式;
printFloat 打印 2.5
printFloat 打印 7.5
这是我到目前为止的代码:
floating-point - 从大十进制数转换为浮点表示
我想我知道如何将十进制数转换为 IEEE 754 单精度浮点表示,但我想确定一下。
我想在 IEEE 754 单精度浮点表示中表示 3.398860921 x 10^18。我知道如何浮动代表。被打破了。
第 31 位:符号(0 表示 +,1 表示 -) 第 30-23 位:表示指数 第 22-0 位:表示尾数(有效位)
所以符号显然是0,因为它是一个正数。对于指数,我想出了这个(通过将 18 添加到 127 的偏差)并将指数表示为:1001 0001
对于 3.398860921 部分的尾数,我不断地将小数点右边的所有内容乘以 2,如果大于 1,我标记为 1,否则标记为 0。然后取新答案并再次将所有内容乘以小数点右边 2,直到我想出足够的位来填充尾数。
所以现在我有: 0 | 1001 0001 | 0110 0110 0001 1011 1011 111
因此,当我将其转换为十六进制时,我得到 0x48B30DDF 但这与我在 3.398860921 x 10^18 中开始的数字不同
应该是这样还是我在某个地方犯了错误?任何帮助将不胜感激。
java - 为什么是 8099.99975f != 8100f?
编辑:我知道浮点运算不准确。算术甚至不是我的问题。加法给出了我预期的结果。8099.99975f
没有。
所以我有这个小程序:
我写它是为了检查写成 IEEE 754 单精度浮点数时8099.99975
是否四舍五入。8100
令我惊讶的是,Java 将其转换8099.9995
为浮点字面量 ( 8099.99975f
)。我再次检查了我的计算和 IEEE 标准,但没有发现任何错误。8100
与 as 相距很远,8099.99975
但8099.9995
最后一点8100
是0
应该使其成为正确的表示形式。
所以我检查了 Java 语言规范,看看我是否遗漏了什么。快速搜索后,我发现了两件事:
-
Java 编程语言要求浮点算术表现得好像每个浮点运算符都将其浮点结果四舍五入到结果精度。不精确的结果必须四舍五入到最接近无限精确结果的可表示值;如果两个最接近的可表示值同样接近,则选择其最低有效位为零的值。
-
Java 编程语言在将浮点值转换为整数时使用向零舍入 [...]。
我注意到这里没有提到浮点文字。所以我认为浮点文字可能只是双精度数,当转换为浮点数时,类似于浮点数到整数转换时四舍五入为零。这可以解释为什么8099.99975f
四舍五入为零。
我编写了您可以在上面看到的小程序来检查我的理论,并且确实发现当添加两个应该导致8100
正确浮点数的浮点文字时,会被计算出来。(请注意,8099.9995
and0.00025
可以完全表示为单个浮点数,因此没有可能导致不同结果的舍入)这让我感到困惑,因为浮点文字和计算浮点的行为不同对我来说没有多大意义,所以我挖了语言规范更多,发现了这个:
如果浮点文字以 ASCII 字母 F 或 f [...] 为后缀,则它的类型为 float。float [...] 类型的元素是可以使用 IEEE 754 32 位单精度 [...] 二进制浮点格式表示的值。
这最终表明文字应该根据 IEEE 标准进行四舍五入,在这种情况下是8100
. 那么为什么会这样8099.9995
呢?
c++ - 十进制转 IEEE 单精度浮点
我有兴趣学习如何仅使用按位运算符将整数值转换为 IEEE 单精度浮点格式。但是,我很困惑在计算指数时可以做些什么来知道还需要多少逻辑移位。
给定一个 int,比如 15,我们有:
二进制:1111
-> 1.111 x 2^3 => 在第一位后放一个小数点后,我们发现'e'值将是3。
E = Exp - 偏差因此,Exp = 130 = 10000010
有效数字为:111000000000000000000000
但是,我知道 'e' 值将是 3,因为我能够看到将小数点放在第一位之后有 3 位。作为一般情况,是否有更通用的编码方式?
同样,这是针对整数到浮点数的转换,假设整数是非负数、非零并且不大于尾数允许的最大空间。
另外,有人可以解释为什么大于 23 位的值需要四舍五入吗?提前致谢!