首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否存在“双”、“K”类型的值,使`K *K == 3.0‘?

是否存在“双”、“K”类型的值,使`K *K == 3.0‘?
EN

Stack Overflow用户
提问于 2022-06-06 00:12:59
回答 5查看 392关注 0票数 7

是否存在double (IEEE 64位浮点数/ binary64)类型的值K,例如K * K == 3.0?(无理数当然是“3的平方根”)

我试过:

代码语言:javascript
运行
复制
static constexpr double Sqrt3 = 1.732050807568877293527446341505872366942805253810380628055806;
static_assert(Sqrt3 * Sqrt3 == 3.0);

但是静态断言失败了。

(我猜,舍入后,3.0的下一个更高或下一个浮点可表示数字平方都不算下一个?)还是浮点文字的解析器很愚蠢?或者它在IEEE标准中是可行的,但是快速的数学优化正在破坏它?)

我认为数字是对的:

代码语言:javascript
运行
复制
$ python

>>> N = 1732050807568877293527446341505872366942805253810380628055806
>>> N * N
2999999999999999999999999999999999999999999999999999999999996\
607078976886330406910974461358291614910225958586655450309636

更新

我发现:

代码语言:javascript
运行
复制
static_assert(Sqrt3 * Sqrt3 < 3.0); // pass
static_assert(Sqrt3 * Sqrt3 > 2.999999999999999); // pass
static_assert(Sqrt3 * Sqrt3 > 2.9999999999999999); // fail

因此,文字必须产生下一个较低的值。

我想我需要检查下一个更高的值。可以转储表示法,然后增加尾数的最后一点。

更新2

对于后代而言:我最后对Sqrt3常量和测试进行了如下操作:

代码语言:javascript
运行
复制
static constexpr double Sqrt3 = 1.7320508075688772;
static_assert(0x1.BB67AE8584CAAP+0 == 1.7320508075688772);
static_assert(Sqrt3 * Sqrt3 == 2.9999999999999996);
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2022-06-06 00:46:00

我认为用Python进行测试是有效的,因为这两种方法都使用IEEE-754表示形式来实现双倍,以及对相同的操作使用规则。

最接近3平方根的二倍是略低的。

代码语言:javascript
运行
复制
>>> Sqrt3 = 3**0.5
>>> Sqrt3*Sqrt3
2.9999999999999996

下一个可用值太高。

代码语言:javascript
运行
复制
>>> import numpy as np
>>> Sqrt3p = np.nextafter(Sqrt3,999)
>>> Sqrt3p*Sqrt3p
3.0000000000000004

如果你能平分的话,你就有了。

代码语言:javascript
运行
复制
>>> Sqrt3*Sqrt3p
3.0
票数 3
EN

Stack Overflow用户

发布于 2022-06-06 01:11:39

C标准没有规定默认的舍入模式。虽然它通常是四舍五入的,但它可能是向上的,而且有些实现支持改变模式。在这种情况下,舍入1.732050807568877193176604123436845839023590087890625而向上四舍五入产生的结果正好是3。

代码语言:javascript
运行
复制
#include <fenv.h>
#include <math.h>
#include <stdio.h>

#pragma STDC FENV_ACCESS ON


int main(void)
{
    volatile double x = 1.732050807568877193176604123436845839023590087890625;
    fesetround(FE_UPWARD);
    printf("%.99g\n", x*x);  // Prints “3”.
}

x被声明为volatile,以防止编译器在编译时使用不同的舍入模式计算x*x。有些编译器不支持#pragma STDC FENV_ACCESS,但在删除#pragma行后可能支持#pragma

票数 8
EN

Stack Overflow用户

发布于 2022-06-06 00:54:21

在Ruby中,Float类使用“本机体系结构的双精度浮点表示”,它有名为prev_floatnext_float的方法,可以使用最小的步骤迭代不同的可能浮动。使用它,我能够做一个简单的测试,并且看到没有符合您的标准的没有 double (至少在x86_64 Linux上是这样)。Ruby解释器是用C编写的,所以我认为我的结果应该适用于C double类型。

下面是Ruby代码:

代码语言:javascript
运行
复制
x = Math.sqrt(3)
4.times { x = x.prev_float }
9.times do
  puts "%.20f squared is %.20f" % [x, x * x]
  puts "Success!" if x * x == 3
  x = x.next_float
end

以及产出:

代码语言:javascript
运行
复制
1.73205080756887630500 squared is 2.99999999999999644729
1.73205080756887652704 squared is 2.99999999999999733546
1.73205080756887674909 squared is 2.99999999999999822364
1.73205080756887697113 squared is 2.99999999999999866773
1.73205080756887719318 squared is 2.99999999999999955591
1.73205080756887741522 squared is 3.00000000000000044409
1.73205080756887763727 squared is 3.00000000000000133227
1.73205080756887785931 squared is 3.00000000000000177636
1.73205080756887808136 squared is 3.00000000000000266454
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72511936

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档