相关疑难解决方法(0)

Printf宽度说明符,用于保持浮点值的精度

是否有printf宽度说明符可以应用于浮点说明符,该说明符会自动将输出格式化为必要的有效位数,以便在重新扫描字符串时,获取原始浮点值?

例如,假设我打印float2小数位数的精度:

float foobar = 0.9375;
printf("%.2f", foobar);    // prints out 0.94
Run Code Online (Sandbox Code Playgroud)

当我扫描输出时0.94,我没有符合标准的保证我将获得原始的0.9375浮点值(在这个例子中,我可能不会).

我想要一种方法告诉printf自动将浮点值打印到必要的有效位数,以确保它可以扫描回传递给的原始值printf.

我可以使用一些宏float.h导出要传递的最大宽度printf,但是是否已经有一个说明符可以自动打印到必要的有效位数 - 或者至少是最大宽度?

c floating-point printf c99 floating-point-precision

84
推荐指数
8
解决办法
21万
查看次数

如何打印浮点数的EXACT值?

首先,这不是浮点新手问题.我知道浮点运算的结果(更不用说超越函数)通常不能准确表示,并且大多数终止小数不能完全表示为二进制浮点数.

也就是说,每个可能的浮点值完全对应于一个二元有理数(一个有理数p/q,其中q是2的幂),而这又有一个精确的十进制表示.

我的问题是:你如何有效地找到这个精确的十进制表示?sprintf类似的函数通常只指定多个有效数字来唯一确定原始浮点值; 它们不一定打印精确的十进制表示.我知道我使用过的一种算法,但它很慢,指数O(e^2)在哪里e.这是一个大纲:

  1. 将尾数转换为十进制整数.你可以通过拉开这些位来直接读取尾数,或者你可以编写一个凌乱的浮点循环,首先将该值乘以2的幂,使其在1 <= x <10的范围内,然后拉通过转换为int,减去并乘以10,一次关闭一个数字.
  2. 通过重复乘以或除以2来应用指数.这是对您生成的十进制数字的操作.每次~3次乘法将在左侧添加一个额外的数字.每个单独的dividion将在右侧添加一个额外的数字.

这真的是最好的吗?我对此表示怀疑,但我不是浮点专家,我无法找到一种方法对数字的浮点表示进行基数10计算,而不会遇到不精确结果的可能性(乘以或除以除了你知道你有空闲位之外,除了2的幂之外的任何东西都是浮点数的有损操作.

c algorithm math floating-point

32
推荐指数
3
解决办法
8759
查看次数

小于 1 的浮点类型可表示的最大值

float有没有办法获得小于 的浮点类型可表示的最大值1

看过以下定义

static const double DoubleOneMinusEpsilon = 0x1.fffffffffffffp-1;
static const float FloatOneMinusEpsilon = 0x1.fffffep-1;
Run Code Online (Sandbox Code Playgroud)

但这真的是我们应该如何定义这些价值观吗?

根据标准,std::numeric_limits<T>::epsilon是机器 epsilon,即 1.0 与浮点类型可表示的下一个值之间的差T。但这并不一定意味着定义T(1) - std::numeric_limits<T>::epsilon会更好。

c++ floating-point epsilon c++17

24
推荐指数
2
解决办法
2200
查看次数

浮点数的十进制精度

相当于log10(2 ^ 24)≈7.225十进制数字

维基百科

精度:7位数

MSDN

6

std::numeric_limits<float>::digits10
Run Code Online (Sandbox Code Playgroud)

为什么numeric_limits在这里返回6?维基百科和MSDN都报告浮点数具有7个十进制数字的精度.

floating-point

12
推荐指数
1
解决办法
1万
查看次数

如何将很长的二进制数转换为十进制?

我有一个二进制数表示为11.1111111(.类似于小数点).在该点之前有2位,在该点之后有1024位.这是一个计算e到高精度的练习,但现在我被困在如何将它转换为十进制.万一你想知道这个数字,这里是:

10.1011011111100001010100010110001010001010111011010010101001101010101111110111000101011000100000001001110011110100111100111100011101100010111001110001011000001111001110001011010011011010010101101010011110000100110110010000010001010001100100001100111111101111001100100100111001110111001110001001001001101100111110111110010111110100101111111000110110001101100011000011000111010111011000111101101000000110110010000000101010111011000100011000010111101011010011110111110001111011010101110101011111110101100101011000010010010000110011111101010001111101011111000001100110111011010000100001010110001101100101010101010011110111101101000110101111001110110101010101110001001101011110011111110101011111001001001101011001100001001111000011000111000011100000111001101000101101110111111000101010011010001001110110101111001111101111111010000111001000011101111100010101100010100001001101101010110111100111001101010011000010101100110010100100111101001000001110100111100101111010101111000000101010110001100000101011001100100100111110110011101011
Run Code Online (Sandbox Code Playgroud)

如何将其转换为2.718 ....(小数点后应该有大约309位)我不能简单地将每个位乘以2 ^ x,因为过了一会儿,数字2 ^ x将= 0,甚至当使用双精度浮子时.我使用的是Visual Basic,所以我不确定是否存在更大的变量.

[由Spektre编辑]

只需用我的代码运行你的字符串(根据我的评论中的链接),结果是:

e(bigdecimal)=2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193200305992181741359662904357290033429526059563073813232862794349076323382988075319525101901157383418793070215408914993488416750924476146066808226480016847741185374234544243710753907774499206955170189257927265177296267786175561825444670874889747782175809270565601486538810885558129926100522647929865142359038501319247028975364903531383896590857864585070203793060262761378008328322397393650711101939331201
e      (text)=2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193200305992181741359662904357290033429526059563073813232862794349076323382988075319525101901157383418793070215408914993488416750924476146066808226480016847741185374234544243710753907774499206955170189
e (reference)=2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427466391932003059921817413596629043572900334295260595630738132328627943490763233829880753195251019011573834187930702154089149934884167509244761460668082264800168477411853742345442437107539077744992069551702761838606261331384583000752044933826560297606737113200709328709127443747047230696977209310141692836819025515108657463772111252389784425056953696770785449969967946864454905987931636889230098793127736178215424999229576351482208269895193668033182528869398496465105820939239829488793320362509443117301238197068416140397019837679320683282376464804295311802328782509819455815301756717361332069811250996181881593041690351598888519345807273866738589422879228499892086805825749279610484198444363463244968487560233624827041978623209002160990235304369941849146314093431738143640546253152096183690888707016768396424378140592714563549061303107208510383750510115747704171898610687396965521267154688957035035402123407849819334321068170121005627880235193033224745015853904730419957777093503660416997329725088687696640355570716226844716256079882651787134195124665201030592123667719432527867539855894489697096409754591856956380236370162112047742722836489613422516445078182442352948636372141740238893441247963574370263755294448337998016125492278509257782562092622648326277933386566481627725164019105900491644998289315056604725802778631864155195653244258698294695930801915298721172556347546396447910145904090586298496791287406870504895858671747985466775757320568128845920541334053922000113786300945560688166740016984205580403363795376452030402432256613527836951177883863874439662532249850654995886234281899707733276171783928034946501434558897071942586398772754710962953741521115136835062752602326484728703920764310059584116612054529703023647254929666938115137322753645098889031360205724817658511806303644281231496550704751025446501172721155519486685080036853228183152196003735625279449515828418829478761085263981395599006737648292244375287184624578036192981971399147564488262603903381441823262515097482798777996437308997038886778227138360577297882412561190717663946507063304527954661855096666185664709711344474016070462621568071748187784437143698821855967095910259686200235371858874856965220005031173439207321139080329363447972735595527734907178379342163701205005451326383544000186323991490705479778056697853358048966906295119432473099587655236812859041383241160722602998330535370876138939639177957454016137223618789365260538155841587186925538606164779834025435128
Run Code Online (Sandbox Code Playgroud)

第一个是从文本转换为我的arbnum数据类型,然后转换回文本,中间是纯文本到文本转换(如在转换为十六进制之前的链接),最后是引用e

这里是二进制字符串的十六进制字符串:

e (hex)      =2.B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF324E7738926CFBE5F4BF8D8D8C31D763DA06C80ABB1185EB4F7C7B5757F5958490CFD47D7C19BB42158D9554F7B46BCED55C4D79FD5F24D6613C31C3839A2DDF8A9A276BCFBFA1C877C56284DAB79CD4C2B3293D20E9E5EAF02AC60ACC93ECEBh
Run Code Online (Sandbox Code Playgroud)

我截断了十进制半字节大小,所以最后可能会留下1,2或3位未经处理的...

vb.net math eulers-number

6
推荐指数
1
解决办法
1078
查看次数

为什么在java中String.format 0.1d double值精确为0.1?

IEEE 754浮点数是离散的。

public class MyTest2 {
  public static void main(String[] args) {
    //about 1.00000001490116119384765625E-1 in IEEE-754
    float f = 0.1f;
    //about 1.00000000000000005551115123126E-1 in IEEE-754
    double d = 0.1d;
    System.out.println(String.format("double 0.1= %.30f", d));
    System.out.println(String.format("float 0.1 = %.15f", f));
    System.out.println(d+"");
  }
}
Run Code Online (Sandbox Code Playgroud)

请参阅在 IdeOne.com 上实时运行的代码。在JDK8中运行,输出为

double 0.1= 0.100000000000000000000000000000
float 0.1 = 0.100000001490116
0.1
Run Code Online (Sandbox Code Playgroud)

浮点值按预期打印。我希望打印双精度值 0.1d 类似 1.000000000000000055511151231260。为什么它在小数部分打印全零

如果我将双精度变量 d 转换为字符串,它会打印 0.1。

System.out.println(d+"");
Run Code Online (Sandbox Code Playgroud)

java如何将最接近的浮点值0.1d(大约为1.00000001490116119384765625E-1)转换为精确的0.1?

java ieee-754

6
推荐指数
1
解决办法
729
查看次数

在 C 中如何确定 FLT_DIG、DBL_DIG 和 LDBL_DIG

FLT_DIG、DBL_DIG、LDBL_DIG分别是float、double、long double类型可以准确表示的十进制位数。

#include <stdio.h>
#include <float.h>

int main(void)
{
  printf("%d, %d, %d\n", FLT_DIG, DBL_DIG, LDBL_DIG);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

打印61518。该标准在第 5.2.4.2.2 节中给出了准确的公式——例如对于浮点数,p = 24 和 b = 2:

在此处输入图片说明

但我不清楚上述公式(“否则”)是如何推导出来的。有人可以解释一下吗?

以下是我遵循的推理,但没有回答问题。考虑在有效数中有 23 位的 float 类型(IEEE-754 标准)。可以准确表示的最大二进制整数为:

  100...00 (25 digits total, because we have an implicit 1)
  = 2^24
  = 10^(24*log(2)) 
Run Code Online (Sandbox Code Playgroud)

因此 # 十进制数字:

= floor(24*log(2)) = 7
Run Code Online (Sandbox Code Playgroud)

而且不像floor(23 * log(2)) = 6标准规定的那样。

c floating-point precision floating-accuracy

5
推荐指数
1
解决办法
1241
查看次数

从 Raku nativecall 调用时精度不同

我正在寻找编写linspaceNumPy 的函数。

由于编译代码中的循环速度更快,因此尝试用 C 编写并从 Raku 调用。

//  C code
#include <stdio.h> 
#ifdef _WIN32 
#define DLLEXPORT __declspec(dllexport)
#else 
#define DLLEXPORT extern // if c++ code, requires extern "C"
#endif

DLLEXPORT void c_linspace(double start, double step, int num, double* vals) {
    for (int i = 0; i < num; i++)
{
    vals[i] = start;
    start += step;
}
}
Run Code Online (Sandbox Code Playgroud)
// Raku code
sub c_linspace(num64, num64, int32, CArray[num64]) 
    is native( MYDYN) { * };

sub raku_linspace($start, $end, $num, :$endpoint = …
Run Code Online (Sandbox Code Playgroud)

c rakudo nativecall raku

5
推荐指数
1
解决办法
181
查看次数

为什么 Rust 只使用 16 位有效数字进行 f64 相等检查?

我有以下 Rust 代码:

use std::f64::consts as f64;

fn main() {
    println!("Checking f64 PI...");
    // f64::PI definition: https://github.com/rust-lang/rust/blob/e1fc9ff4a794fb069d670dded1a66f05c86f3555/library/core/src/num/f64.rs#L240
    println!("Definition: pub const PI: f64 = 3.14159265358979323846264338327950288_f64;");
    println!("Print it:                       {:.35}", f64::PI);
    println!("Different after 16 significant digits ----------|                         ");
    println!("##############################################################################");
    println!("Question 1: Why do the digits differ after 16 significant digits when printed?");
    println!("##############################################################################");

    println!("PERFORM ASSERTIONS..."); 
    assert_eq!(f64::PI, 3.14159265358979323846264338327950288_f64); // 36 significant digits definition
    assert_eq!(f64::PI, 3.141592653589793_f64); // 16 significant digits (less then the 36 in definition)
    // compares up to here -------------|
    assert_eq!(f64::PI, 3.14159265358979300000000000000000000_f64); // …
Run Code Online (Sandbox Code Playgroud)

floating-point precision rust

3
推荐指数
1
解决办法
135
查看次数

在 C 中,如何将 float/double 作为字符串打印并将其作为相同的 float 读回?

我想知道实现这一目标的最简单、最便携且普遍认为的最佳实践,适用于任何数字。我还希望与数字关联的字符串采用十进制表示形式,如果可能的话,不使用科学记数法。

c string floating-point

3
推荐指数
1
解决办法
419
查看次数

如果float有6位精度,为什么我们可以用printf显示超过6位的浮点数?

让我们考虑下面的代码:

#include <stdio.h>
int main()
{
    float x = 0.33;
    printf("%.100f",x);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果float有6位精度,那么如何用 来显示超过6位的数字printf

c floating-point precision

2
推荐指数
1
解决办法
432
查看次数

如何在源代码中精确表达浮点常量

我有一些通过代码生成器生成的 C++11 代码,其中包含大量浮点数,并且我想确保编译值与生成器中的编译值完全相同(假设两者都依赖于相同的值)浮动 ISO 标准)

因此,我认为最好的方法是将值存储为十六进制表示形式,并将它们解释为代码中的浮点数。

编辑以澄清: 代码生成器获取浮点值并将它们转换为相应的十六进制表示形式。目标代码应该转换回浮点数。

它看起来像这样:

const unsigned int data[3] = { 0x3d13f407U, 0x3ea27884U, 0xbe072dddU};
float const* ptr = reinterpret_cast<float const*>(&data[0]);
Run Code Online (Sandbox Code Playgroud)

这有效并允许我以浮点形式访问所有数据元素,但我最近偶然发现这实际上是未定义的行为,并且仅有效,因为我的编译器按照我的预期方式解析了它:

https://gist.github.com/shafik/848ae25ee209f698763cffee272a58f8

https://en.cppreference.com/w/cpp/language/reinterpret_cast

该标准基本上表示reinterpret_cast不同类型的 POD 指针之间没有定义。

所以基本上我有三个选择:

  1. 使用memcopy并希望编译器能够对此进行优化

  2. 不将数据存储为十六进制值,而是以不同的方式存储。

  3. std::bit_cast从 C++20开始使用。

我无法使用 3),因为我坚持使用 C++11。

我没有资源来存储数据数组两次,所以我必须依靠编译器来优化它。因此,我不太喜欢 1),因为如果我更改编译器或编译器设置,它可能会停止工作。

所以我只剩下2):

是否有一种标准化的方法来在源代码中表达浮点值,以便它们在编译时映射到精确的浮点值?ISO 浮点标准是否以保证任何编译器都会遵循解释的方式定义了这一点?我想如果我偏离编译器期望的方式,我可能会冒使用我实际想要的数字的浮点“邻居”的风险。

如果有我忘记的选项 4,我也会采取其他想法。

c++ c++11 floating-point-conversion

1
推荐指数
1
解决办法
265
查看次数

浮点戏剧性错误(小数部分完全丢失)

quotient = 43156414f / 3;
Run Code Online (Sandbox Code Playgroud)

我在这里得到quotient== 1438547 2(完全不是真正的价值应该是: 1438547 1,333...)。它完全失去了所有小数部分!

我知道浮点计算不准确(似乎不是全部,我应该知道),但是,正如我所告知的,错误可能出现在更远的有效数字上。但这里的红利只是 8 位数字。为什么会发生如此戏剧性的错误?

可选的子问题:我应该记住哪些规则来预见未来的此类错误?

请注意:将分红类型从 float 更改为 double 可以解决此问题。

c# precision floating-accuracy

0
推荐指数
1
解决办法
64
查看次数