我面临一个好奇的问题。查看此简单的代码:
int main(int argc, char **argv) {
char buf[1000];
snprintf_l(buf, sizeof(buf), _LIBCPP_GET_C_LOCALE, "%.17f", 0.123e30f);
std::cout << "WTF?: " << buf << std::endl;
}
输出看起来Quire Quire:
123000004117574256822262431744.00000000000000000
我的问题是如何实现?有人可以告诉我原始代码吗?我没有找到。也许这对我来说太复杂了。
我试图用Java代码重新将相同的转换重新输入到字符串,但失败了。即使我试图分别获取指数和分数零件并在周期中总结分数,我也总是会得到零数而不是这些数字“ ... 8222262431744”。当我尝试在23位(对于浮点数)之后继续总结分数时,我面对其他问题 - 我需要收集多少个部分?为什么原始代码在左侧停止而直到量表结束之前才继续?
因此,我真的不了解基本逻辑,如何实现。我尝试定义数字非常大(例如0.123E127F)。它以小数格式产生了大量。该数字的精度比浮子要高得多。看起来这是一个问题,因为字符串表示包含浮点数不能的东西。
I faced with a curious issue. Look at this simple code:
int main(int argc, char **argv) {
char buf[1000];
snprintf_l(buf, sizeof(buf), _LIBCPP_GET_C_LOCALE, "%.17f", 0.123e30f);
std::cout << "WTF?: " << buf << std::endl;
}
The output looks quire wired:
123000004117574256822262431744.00000000000000000
My question is how it's implemented? Can someone show me the original code? I did not find it. Or maybe it's too complicated for me.
I've tried to reimplement the same transformation double to string with Java code but was failed. Even when I tried to get exponent and fraction parts separately and summarize fractions in cycle I always get zeros instead of these numbers "...822262431744". When I tried to continue summarizing fractions after the 23 bits (for float number) I faced with other issue - how many fractions I need to collect? Why the original code stops on left part and does not continue until the scale is end?
So, I really do not understand the basic logic, how it implemented. I've tried to define really big numbers (e.g. 0.123e127f). And it generates huge number in decimal format. The number has much higher precision than float can be. Looks like this is an issue, because the string representation contains something which float number cannot.
发布评论
评论(3)
请阅读文档:
printf,fprintf,sprintf,snprintf,snprintf,printf_s,printf_s,fprintf_s,fprintf_s,sprintf_s,snprintf_s,snprintf_s-s-s sn snprintf_s-- cppreference.com
而使用
f
您强制表格ddd.ddd
(无exponent)和.17
您已被迫在小数分离器后显示17位数字。如此大的价值印刷结果看起来很奇怪。Please read documentation:
printf, fprintf, sprintf, snprintf, printf_s, fprintf_s, sprintf_s, snprintf_s - cppreference.com
So with
f
you forced formddd.ddd
(no exponent) and with.17
you have forced to show 17 digits after decimal separator. With such big value printed outcome looks that odd.最后,我发现了Java Float - &gt;小数 - &gt;字符串转换和C ++ float-&gt;字符串(十进制)转换。我没有找到原始的源代码,但是我在Java中复制了相同的代码以使其清晰。我认为代码解释了一切:
也许主题是没有用的。谁真的需要像C ++一样具有相同的实现?但是至少此代码与最流行的方式将float转换为十进制字符串的浮点数保持了所有精度:
Finally I've found out what the difference between Java float -> decimal -> string conversion and c++ float -> string (decimal) conversion. I did not find the original source code, but I replicated the same code in Java to make it clear. I think the code explains everything:
Maybe topic is useless. Who really need to have the same implementation like C++ has? But at least this code keeps all precision for float number comparing to the most popular way converting float to decimal string:
您使用的C ++实现使用了
float
的IEEE-754 binary32格式。以这种格式,壁橱的代表值为0.123•10 30 为123,000,004,117,117,574,256,822,262,262,431,744,以binary32格式表示为 +13,023,132•2 73 。因此0.123E30F
在源代码中产生的编号为123,000,004,117,574,256,822,262,262,431,744。 (因为数字表示为 +13,023,132•2 73 ,我们知道它的价值正是123,000,004,117,117,574,256,256,822,262,262,262,431,744,即使Digit'您使用
%。17F
格式化,您的C ++实现忠实地打印了确切的值,产生“ 12300000411757425682222222222222222431744.00000000000000000”。 C ++标准不需要这种准确性,并且某些C ++实现不会准确地进行转换。Java规范还不需要浮点值的格式化,至少在某些格式化操作中。 (我在这里从内存和一些假设转移;我没有引用。)它允许,甚至可能需要,只能产生一定数量的正确数字小数点或要求的格式。
对于
float
格式中表示的任何值,该值具有无限的精度。数量 +13,023,132•2 73 是正好 +13,023,132•2 73 ,恰好是123,000,004,004,1174,1174,574,256,256,822,262,262,262,262,262,262,431,744444444444444 4。该格式表示数字的精度仅影响它可以表示的数字,而不是它准确地代表其所代表的数字。The C++ implementation you are using uses the IEEE-754 binary32 format for
float
. In this format, the closet representable value to 0.123•1030 is 123,000,004,117,574,256,822,262,431,744, which is represented in the binary32 format as +13,023,132•273. So0.123e30f
in the source code yields the number 123,000,004,117,574,256,822,262,431,744. (Because the number is represented as +13,023,132•273, we know its value is that exactly, which is 123,000,004,117,574,256,822,262,431,744, even though the digits “123000004117574256822262431744” are not stored directly.)Then, when you format it with
%.17f
, your C++ implementation prints the exact value faithfully, yielding “123000004117574256822262431744.00000000000000000”. This accuracy is not required by the C++ standard, and some C++ implementations will not do the conversion exactly.The Java specification also does not require formatting of floating-point values to be exact, at least in some formatting operations. (I am going from memory and some supposition here; I do not have a citation at hand.) It allows, perhaps even requires, that only a certain number of correct digits be produced, after which zeros are used if needed for positioning relative to the decimal point or for the requested format.
For any value represented in the
float
format, that value has infinite precision. The number +13,023,132•273 is exactly +13,023,132•273, which is exactly 123,000,004,117,574,256,822,262,431,744, to infinite precision. The precision the format has for representing numbers affects only which numbers it can represent, not how precisely it represents the numbers that it does represent.