是否有“双”,“ k”的值,以便`k * k == 3.0`?
是否有类型double
的值(IEEE 64位float/binary64),k
,以便k * k * k == 3.0
? (当然,非理性的数字是“ 3平方根”)
我尝试过:
static constexpr double Sqrt3 = 1.732050807568877293527446341505872366942805253810380628055806;
static_assert(Sqrt3 * Sqrt3 == 3.0);
但是静态断言失败了。
(我猜想下一个较高和下一个较低的浮点数既代表数字平方square to 3.0
?rounding之后?还是浮点的解析器是愚蠢的?还是在IEEE标准中可行,但是快速的数学优化正在弄乱它吗?)
我认为数字是正确的:
$ python
>>> N = 1732050807568877293527446341505872366942805253810380628055806
>>> N * N
2999999999999999999999999999999999999999999999999999999999996\
607078976886330406910974461358291614910225958586655450309636
更新
我已经发现:
static_assert(Sqrt3 * Sqrt3 < 3.0); // pass
static_assert(Sqrt3 * Sqrt3 > 2.999999999999999); // pass
static_assert(Sqrt3 * Sqrt3 > 2.9999999999999999); // fail
因此,字面意思必须产生下一个较低的值。
我想我需要检查下一个更高的值。可能会稍微降低表示形式,然后递增Mantissa的最后一点。
更新2
后代:我将其用于SQRT3常数和测试:
static constexpr double Sqrt3 = 1.7320508075688772;
static_assert(0x1.BB67AE8584CAAP+0 == 1.7320508075688772);
static_assert(Sqrt3 * Sqrt3 == 2.9999999999999996);
Is there a value of type double
(IEEE 64-bit float / binary64), K
, such that K * K == 3.0
? (The irrational number is of course "square root of 3")
I tried:
static constexpr double Sqrt3 = 1.732050807568877293527446341505872366942805253810380628055806;
static_assert(Sqrt3 * Sqrt3 == 3.0);
but the static assert fails.
(I'm guessing neither the next higher nor next lower floating-point representable number square to 3.0
after rounding? Or is the parser of the floating point literal being stupid? Or is it doable in IEEE standard but fast math optimizations are messing it up?)
I think the digits are right:
$ python
>>> N = 1732050807568877293527446341505872366942805253810380628055806
>>> N * N
2999999999999999999999999999999999999999999999999999999999996\
607078976886330406910974461358291614910225958586655450309636
Update
I've discovered that:
static_assert(Sqrt3 * Sqrt3 < 3.0); // pass
static_assert(Sqrt3 * Sqrt3 > 2.999999999999999); // pass
static_assert(Sqrt3 * Sqrt3 > 2.9999999999999999); // fail
So the literal must produce the next lower value.
I guess I need to check the next higher value. Could bit-dump the representation maybe and then increment the last bit of the mantissa.
Update 2
For posterity: I wound up going with this for the Sqrt3 constant and the test:
static constexpr double Sqrt3 = 1.7320508075688772;
static_assert(0x1.BB67AE8584CAAP+0 == 1.7320508075688772);
static_assert(Sqrt3 * Sqrt3 == 2.9999999999999996);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
答案是否定的;没有这样的
k
。最接近3的平方根的二进制64值等于7800463371553962&nbsp;×2 -52 。它的广场为:
608472288109550042211586778974444×2 -104
此值并非完全可以表示。 )和3之间,分别等于
608472228881095500226464242424999917056
它介于(3&nbsp; - &nbsp; 2 -51
×2 -104 /sup>,
如您所见,
k * k
比3 更接近3&nbsp; - &nbsp; - &nbsp; - &nbsp; sup> 比3。操作k * k
以3&nbsp; - &nbsp; 2 -51 而不是3。(编译器可能会将k
转换为扩展计算的精确格式,但结果仍将为3&nbsp; - &nbsp; 2 -51 转换回二进制64。 /code>在binary64格式中,我们会发现其平方最接近3&nbsp;+&nbsp; 2 -51 ,这是3个以后的下一个代表值。
此结果不应该太惊讶;通常,将数字增加1 ULP将大约2 ULP递增其正方形,因此,给定一些值
x
,您有大约50%的机会,有一个k
具有与x
相同的精度,以便k * k == x
。The answer is no; there is no such
K
.The closest binary64 value to the actual square root of 3 is equal to 7800463371553962 × 2-52. Its square is:
60847228810955004221158677897444 × 2-104
This value is not exactly representable. It falls between (3 - 2-51) and 3, which are respectively equal to
60847228810955002264642499117056 × 2-104
and
60847228810955011271841753858048 × 2-104
As you can see,
K * K
is much closer to 3 - 2-51 than it is to 3. So IEEE 754 requires the result of the operationK * K
to yield 3 - 2-51, not 3. (The compiler might convertK
to an extended-precision format for the calculation, but the result will still be 3 - 2-51 after conversion back to binary64.)Furthermore, if we go to the next representable value after
K
in the binary64 format, we will find that its square is closest to 3 + 2-51, which is the next representable value after 3.This result should not be too surprising; in general, incrementing a number by 1 ulp will increment its square by roughly 2 ulps, so you have about a 50% chance, given some value
x
, that there is aK
with the same precision asx
such thatK * K == x
.C标准不规定默认的舍入模式。尽管它通常是最圆的,即使是沿线的,它也可能是向上圆的,并且某些实现支持更改模式。 In such case, squaring 1.732050807568877193176604123436845839023590087890625 while rounding upward produces exactly 3.
x
is declaredvolatile
to prevent the compiler from computingx*x
at compile-有不同的圆形模式的时间。一些编译器不支持#pragma stdc fenv_access
,但是一旦删除了#pragma
行,可以支持fesetround
。The C standard does not dictate the default rounding mode. While it is typically round-to-nearest, ties-to-even, it could be round-upward, and some implementations support changing the mode. In such case, squaring 1.732050807568877193176604123436845839023590087890625 while rounding upward produces exactly 3.
x
is declaredvolatile
to prevent the compiler from computingx*x
at compile-time with a different rounding mode. Some compilers do not support#pragma STDC FENV_ACCESS
but may supportfesetround
once the#pragma
line is removed.我认为使用Python进行测试是有效的,因为两者都使用IEEE-754表示双打以及对操作的规则。
最接近3平方根的双重双重略低。
下一个可用值太高。
如果您可以将差异分开,那就可以了。
Testing with Python is valid I think, since both use the IEEE-754 representation for doubles along with the rules for operations on same.
The closest possible double to the square root of 3 is slightly low.
The next available value is too high.
If you could split the difference, you'd have it.
在Ruby语言中,
float
类使用“本机体系结构的双精度浮点表示”,它具有名为prev_float
和next_float
的方法让您使用最小的步骤通过不同可能的浮子进行迭代。使用此功能,我能够进行简单的测试,并看到 nodouble
(至少在x86_64 linux上)符合您的标准。 Ruby解释器用C编写,因此我认为我的结果应适用于Cdouble
类型。这是红宝石代码:
和输出:
In the Ruby language, the
Float
class uses "the native architecture's double-precision floating point representation" and it has methods namedprev_float
andnext_float
that let you iterate through different possible floats using the smallest possible steps. Using this, I was able to do a simple test and see that there is nodouble
(at least on x86_64 Linux) that meets your criterion. The Ruby interpreter is written in C, so I think my results should be applicable to the Cdouble
type.Here is the Ruby code:
And the output:
是的。
k = sqrt(n);
和k * k * k == n
也可能是正确的,即使√n
是不合理的。请注意,
k
,sqrt(n)
的结果,作为double
,是一个有理数。各种四舍五入模式:@@ericer
k * k * k * k
roundsn
示例:roots
n
:11、14和17平方是n
。而不是53位,带有常见的
double
,例如使用24个fp数学。代码>。或说FP数学是用64位完成的。 roots
n
:5、6和10平方为n
。对于各种精确度,(注意C未指定固定精度),
k * k == 3.0
是可能的。flt_eval_method == 2
当
flt_eval_method == 2
时,可以在更高的进pessions上进行中间计算,从而影响k*k*k*k*k
的产物。(尚未提出一个很好的简单例子。)
Yes.
K = sqrt(n);
andK * K == n
may be true, even when √n
is irrational.Note that
K
, the result ofsqrt(n)
, as adouble
, is a rational number.Various rounding modes: @Eric
K * K
rounds ton
Example: Roots
n
: 11, 14 and 17 when squared aren
.Rather than 53 bits with common
double
, say the FP math was done with 24. Rootsn
: 3, 5 and 10 when squared aren
.or say the FP math was done with 64 bits. Roots
n
: 5, 6 and 10 when squared aren
.With various precisions, (note C does not specify a fixed precision),
K * K == 3.0
is possible.FLT_EVAL_METHOD == 2
When
FLT_EVAL_METHOD == 2
, intermediate calculations may be done at higher precession, thus affecting the product ofk*k
.(Have yet to come up with a good simple example.)
sqrt(3)
是不合理的,这意味着没有理性的数字k,因此k*k == 3
。双重只能表示有理数;因此,没有double k
,因此k*k == 3
。如果您可以接受一个 close 满足
k*k == 3
的数字,那么您可以使用std :: nemeric_limits
(in <代码>&lt; type_traits&gt; ,如果内存使用),以查看您是否在3个最小间隔内。看起来像:epsilon是与double可以表示的最小区别。我们按两个值的总和进行比较,以使其幅度与我们要检查的数字保持一致。 X是一个缩放因素,可让您调整所接受的精度。
如果这是一个理论上的问题:否。如果这是一个实际的问题:是的,提高一定程度的精度。
sqrt(3)
is irrational, which means that there is no rational number k such thatk*k == 3
. A double can only represent rational numbers; therefore, there is nodouble k
such thatk*k == 3
.If you can accept a number that is close to satisfying
k*k == 3
, then you can usestd::numeric_limits
(in<type_traits>
, if memory serves) to see if you’re within some minimal interval around 3. It may look like:Epsilon is the smallest difference from one that double can represent. We scale it by the sum of the two values to compare in order to bring its magnitude in line with the numbers we’re checking. X is a scaling factor that lets you adjust the precision you accept.
If this is a theoretical question: no. If it’s a practical question: yes, up some level of precision.