如何在 C++ 中将双精度转换为 C# 十进制
How to convert a double to a C# decimal in C++?
鉴于我有十进制的改写 - 例如,你可以在这里找到它--,我试图以这种方式转换双精度:
explicit Decimal(double n)
{
DoubleAsQWord doubleAsQWord;
doubleAsQWord.doubleValue = n;
uint64 val = doubleAsQWord.qWord;
const uint64 topBitMask = (int64)(0x1 << 31) << 32;
//grab the 63th bit
bool isNegative = (val & topBitMask) != 0;
//bias is 1023=2^(k-1)-1, where k is 11 for double
uint32 exponent = (((uint64)(val >> 31) >> 21) & 0x7FF) - 1023;
//exclude both sign and exponent (<<12, >>12) and normalize mantissa
uint64 mantissa = ((uint64)(0x1 << 31) << 21) | (val << 12) >> 12;
// normalized mantissa is 53 bits long,
// the exponent does not care about normalizing bit
uint8 scale = exponent + 11;
if (scale > 11)
scale = 11;
else if (scale < 0)
scale = 0;
lo_ = ((isNegative ? -1 : 1) * n) * std::pow(10., scale);
signScale_ = (isNegative ? 0x1 : 0x0) | (scale << 1);
// will always be 0 since we cannot reach
// a 128 bits precision with a 64 bits double
hi_ = 0;
}
DoubleAsQWord 类型用于从 double "转换"到其 uint64 表示形式:
union DoubleAsQWord
{
double doubleValue;
uint64 qWord;
};
我的十进制类型具有以下字段:
uint64 lo_;
uint32 hi_;
int32 signScale_;
所有这些东西都封装在我的十进制类中。你可以注意到我提取了尾数,即使我不使用它。我还在想一种准确猜测比例的方法。
这纯粹是实用的,似乎在压力测试的情况下有效:
BOOST_AUTO_TEST_CASE( convertion_random_stress )
{
const double EPSILON = 0.000001f;
srand(time(0));
for (int i = 0; i < 10000; ++i)
{
double d1 = ((rand() % 10) % 2 == 0 ? -1 : 1)
* (double)(rand() % 1000 + 1000.) / (double)(rand() % 42 + 2.);
Decimal d(d1);
double d2 = d.toDouble();
double absError = fabs(d1 - d2);
BOOST_CHECK_MESSAGE(
absError <= EPSILON,
"absError=" << absError << " with " << d1 << " - " << d2
);
}
}
无论如何,您将如何从double
转换为这种decimal
表示?
我想你们会对英特尔十进制浮点数学库的C++包装器的实施感兴趣:
C++ 十进制包装类
英特尔 DFP
使用 VarR8FromDec 函数怎么样?
编辑:此功能仅在Windows系统上声明。但是,WINE 提供了等效的 C 实现,如下所示:http://source.winehq.org/source/dlls/oleaut32/vartype.c
也许你正在寻找System::Convert::ToDecimal()
http://msdn.microsoft.com/en-us/library/a69w9ca0%28v=vs.80%29.aspx
或者,您可以尝试将 Double 重新转换为十进制。
MSDN 中的一个示例。
http://msdn.microsoft.com/en-us/library/aa326763%28v=vs.71%29.aspx
// Convert the double argument; catch exceptions that are thrown.
void DecimalFromDouble( double argument )
{
Object* decValue;
// Convert the double argument to a Decimal value.
try
{
decValue = __box( (Decimal)argument );
}
catch( Exception* ex )
{
decValue = GetExceptionType( ex );
}
Console::WriteLine( formatter, __box( argument ), decValue );
}
如果您无权访问 .Net 例程,那么这很棘手。 我自己为我的十六进制编辑器完成了此操作(以便用户可以使用"属性"对话框显示和编辑 C# 十进制值) - 有关详细信息,请参阅 http://www.hexedit.com。 此外,HexEdit的来源是免费提供的 - 请参阅我在 http://www.codeproject.com/KB/cpp/HexEdit.aspx 上的文章。
实际上我的例程在十进制和字符串之间转换,但您当然可以使用 sprintf 先将双精度转换为字符串。 (同样,当你谈论双精度时,我认为你明确指的是IEEE 64位浮点格式,尽管这是现在大多数编译器/系统使用的格式。
请注意,如果要精确处理所有有效的十进制值并为无法转换的任何值返回错误,则有一些陷阱,因为格式没有很好的文档记录。 (十进制格式确实令人敬畏,例如相同的数字可以有很多表示形式。
这是我将字符串转换为小数的代码。 请注意,它使用 GNU 多精度算术库(以 mpz_ 开头的函数)。 如果 String2Decimal 函数由于某种原因(例如值太大)失败,则显然会返回 false。 参数 'presult' 必须指向至少 16 个字节的缓冲区来存储结果。
bool String2Decimal(const char *ss, void *presult)
{
bool retval = false;
// View the decimal (result) as four 32 bit integers
unsigned __int32 *dd = (unsigned __int32 *)presult;
mpz_t mant, max_mant;
mpz_inits(mant, max_mant, NULL);
int exp = 0; // Exponent
bool dpseen = false; // decimal point seen yet?
bool neg = false; // minus sign seen?
// Scan the characters of the value
const char *pp;
for (pp = ss; *pp != ' '; ++pp)
{
if (*pp == '-')
{
if (pp != ss)
goto exit_func; // minus sign not at start
neg = true;
}
else if (isdigit(*pp))
{
mpz_mul_si(mant, mant, 10);
mpz_add_ui(mant, mant, unsigned(*pp - '0'));
if (dpseen) ++exp; // Keep track of digits after decimal pt
}
else if (*pp == '.')
{
if (dpseen)
goto exit_func; // more than one decimal point
dpseen = true;
}
else if (*pp == 'e' || *pp == 'E')
{
char *end;
exp -= strtol(pp+1, &end, 10);
pp = end;
break;
}
else
goto exit_func; // unexpected character
}
if (*pp != ' ')
goto exit_func; // extra characters after end
if (exp < -28 || exp > 28)
goto exit_func; // exponent outside valid range
// Adjust mantissa for -ve exponent
if (exp < 0)
{
mpz_t tmp;
mpz_init_set_si(tmp, 10);
mpz_pow_ui(tmp, tmp, -exp);
mpz_mul(mant, mant, tmp);
mpz_clear(tmp);
exp = 0;
}
// Get max_mant = size of largest mantissa (2^96 - 1)
//mpz_set_str(max_mant, "79228162514264337593543950335", 10); // 2^96 - 1
static unsigned __int32 ffs[3] = { 0xFFFFffffUL, 0xFFFFffffUL, 0xFFFFffffUL };
mpz_import(max_mant, 3, -1, sizeof(ffs[0]), 0, 0, ffs);
// Check for mantissa too big.
if (mpz_cmp(mant, max_mant) > 0)
goto exit_func; // value too big
else if (mpz_sgn(mant) == 0)
exp = 0; // if mantissa is zero make everything zero
// Set integer part
dd[2] = mpz_getlimbn(mant, 2);
dd[1] = mpz_getlimbn(mant, 1);
dd[0] = mpz_getlimbn(mant, 0);
// Set exponent and sign
dd[3] = exp << 16;
if (neg && mpz_sgn(mant) > 0)
dd[3] |= 0x80000000;
retval = true; // indicate success
exit_func:
mpz_clears(mant, max_mant, NULL);
return retval;
}
这个怎么样:
1) 冲刺数成 S2)查找小数点(strchr),存储在IDX中3) atoi = 轻松获得整数部分,使用并集分离高/低4) 使用 strlen - idx 获取点后的位数
sprintf 可能会很慢,但您将在 2 分钟内输入得到解决方案......
- visual在c++中将十进制数转换为二进制数
- C++十进制到二进制,如何转换
- C++从二进制转换为十进制数
- 我编写了代码将十进制分数转换为其二进制等效数.它编译得很好,但在执行时挂起
- 将分数转换为十进制数并对其进行排序
- 将字符串(可以是十进制字符串或十六进制字符串)转换为整数C++
- 十进制到二进制转换器 c++
- 如何在C ++中将二进制字符串128位转换为十进制字符串?
- 将二进制转换为十进制,我如何要求用户仅输入二进制
- 我正在尝试编写将 ASCII 转换为十进制、添加并转换回 ASCII 的软件
- 如何将QBytearrayBCD转换为十进制QString表示
- C++:二进制到十进制w/转换过程的外观
- 十六进制到十进制转换的未清理答案
- 如何在C++中将二进制编码十进制转换为 int
- 如何将带有浮点数的字符串转换为十进制?
- 如何使用链表将负十进制数转换为二进制?
- 将字符指针中的十六进制转换为十进制
- 使用 std::hex 将十六进制转换为十进制
- 十进制,包括负到 32 位二进制转换器
- 使用动态比特斯转换十进制数字