Hi, I need to implement a function that should take a double and split
it into two integers. The decimalpart may be 0 but it may not be
greater than 0.99 and not less than 0.01. In other words, decimalparts
larger than three decimals are invalid input. I know floating point
numbers are not represented exactly in computers so this is tricky
business. This seems to work on my laptop, it's to be used by students
in an assignment to write a monetary class so it mustn't be perfect,
but I would like to hear your input.
#include <cmath>
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
void split_double(co nst double num, int& integer, int& decimals)
{
const int precision = 2;
double d1, d2;
d1 = modf(num, &d2);
if(d1 != 0.0f && (d1 0.99f || d1 < 0.01f))
cout << "d1 = " << d1 << " Error!" << endl; // TODO: Throw
exception
stringstream ss;
ss << fixed << setprecision(pr ecision) << num;
ss >integer;
ss.ignore();
ss >decimals;
}
int main()
{
int intpart;
int decpart;
split_double(3. 99, intpart, decpart);
cout << intpart << "." << decpart << endl;
split_double(3. 991, intpart, decpart);
cout << intpart << "." << decpart << endl;
split_double(3. 001, intpart, decpart);
cout << intpart << "." << decpart << endl;
}
$ ./foo.exe
3.99
d1 = 0.991 Error!
3.99
d1 = 0.001 Error!
3.0 6 9314
Hi Eric,
This function does what you want:
#include <cmath>
void split_double(do uble d, int precision,
int &integer_par t, int &fractional_par t)
{
integer_part = (int)d;
fractional_part = (int)( (d - integer_part) * std::pow(10,
precision) + 0.5);
}
The +0.5 in the integer cast is to achieve proper rounding. For
example, if precision is 3, then 0.4567 will round to 0.457 instead of
0.456.
If you need the function to be fast, then the call to pow() should
probably be optimized out somehow (or just hard code the function to a
particular precision).
Regards,
Markus.
Eric Lilja wrote:
Hi, I need to implement a function that should take a double and split
it into two integers. The decimalpart may be 0 but it may not be
greater than 0.99 and not less than 0.01. In other words, decimalparts
larger than three decimals are invalid input. I know floating point
numbers are not represented exactly in computers so this is tricky
business. This seems to work on my laptop, it's to be used by students
in an assignment to write a monetary class so it mustn't be perfect,
but I would like to hear your input.
#include <cmath>
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
void split_double(co nst double num, int& integer, int& decimals)
{
const int precision = 2;
double d1, d2;
d1 = modf(num, &d2);
if(d1 != 0.0f && (d1 0.99f || d1 < 0.01f))
cout << "d1 = " << d1 << " Error!" << endl; // TODO: Throw
exception
stringstream ss;
ss << fixed << setprecision(pr ecision) << num;
ss >integer;
ss.ignore();
ss >decimals;
}
int main()
{
int intpart;
int decpart;
split_double(3. 99, intpart, decpart);
cout << intpart << "." << decpart << endl;
split_double(3. 991, intpart, decpart);
cout << intpart << "." << decpart << endl;
split_double(3. 001, intpart, decpart);
cout << intpart << "." << decpart << endl;
}
$ ./foo.exe
3.99
d1 = 0.991 Error!
3.99
d1 = 0.001 Error!
3.0
Markus Svilans wrote:
Hi Eric,
This function does what you want:
#include <cmath>
void split_double(do uble d, int precision,
int &integer_par t, int &fractional_par t)
{
integer_part = (int)d;
fractional_part = (int)( (d - integer_part) * std::pow(10,
precision) + 0.5);
}
The +0.5 in the integer cast is to achieve proper rounding. For
example, if precision is 3, then 0.4567 will round to 0.457 instead of
0.456.
There are several rounding behaviors possible (round toward nearest,
round toward zero, round away from zero and so forth). The rounding
behavior that happens to be the "proper" one depends on the
application. And in this case, if the proper behavior to round to the
nearest three-digit decimal fractional representation, then adding 0.5
will not work for all values: for example -0.4567 will round to -0.456
even though -0.467 is closer in value.
A program can readily divide a double into integer and one-thousandth
units (rounding toward nearest represention) like so:
#include <math.h>
// d is the double
int integerUnits = d; // truncate
int fractionalUnits = fmod( round(d * 1000.0), 1000.0);
Greg
Hi Greg,
You're right, the solution I gave only rounds positive numbers
"properly."
Another possible correction is:
fractional_part = (int)( (d - integer_part) * std::pow(10, precision) +
(d 0 ? 0.5 : -0.5) );
The expression could be simplified by using a constant value (e.g. 100,
1000, or 10000) instead of the slower pow() function.
Thanks,
Markus.
Greg wrote:
Markus Svilans wrote:
Hi Eric,
This function does what you want:
#include <cmath>
void split_double(do uble d, int precision,
int &integer_par t, int &fractional_par t)
{
integer_part = (int)d;
fractional_part = (int)( (d - integer_part) * std::pow(10,
precision) + 0.5);
}
The +0.5 in the integer cast is to achieve proper rounding. For
example, if precision is 3, then 0.4567 will round to 0.457 instead of
0.456.
There are several rounding behaviors possible (round toward nearest,
round toward zero, round away from zero and so forth). The rounding
behavior that happens to be the "proper" one depends on the
application. And in this case, if the proper behavior to round to the
nearest three-digit decimal fractional representation, then adding 0.5
will not work for all values: for example -0.4567 will round to -0.456
even though -0.467 is closer in value.
A program can readily divide a double into integer and one-thousandth
units (rounding toward nearest represention) like so:
#include <math.h>
// d is the double
int integerUnits = d; // truncate
int fractionalUnits = fmod( round(d * 1000.0), 1000.0);
Greg
Markus Svilans wrote:
Hi Greg,
You're right, the solution I gave only rounds positive numbers
"properly."
Another possible correction is:
fractional_part = (int)( (d - integer_part) * std::pow(10, precision) +
(d 0 ? 0.5 : -0.5) );
The expression could be simplified by using a constant value (e.g. 100,
1000, or 10000) instead of the slower pow() function.
Another way to avoid the runtime overhead of calling pow() would be to
calculate the value as a compile time constant:
template <int Base, unsigned Exponent>
struct Power
{
const static int value = Base * Power<Base, Exponent-1>::value;
};
template <int Base>
struct Power<Base, 0>
{
const static int value = 1;
};
With the call to pow() replaced with the Power class template
"metafuncti on", there is no additional overhead in implementing
SplitDouble as a template function (with the desired precision
specified as its non-type parameter):
template <unsigned N>
void SplitDouble(dou ble d, int& outInteger, int& outFraction)
{
int outInteger = d; // truncate
int outFraction = fmod( round(d * Power<10, N>::value),
Power<10, N>::value);
}
To obtain the two digit precision required in the original post, a
program would call SplitDouble like so:
int integerUnits, fractionalUnits ;
SplitDouble<2>( d, integerUnits, fractionalUnits );
Greg
Eric Lilja wrote:
Hi, I need to implement a function that should take a double and split
it into two integers. The decimalpart may be 0 but it may not be
greater than 0.99 and not less than 0.01. In other words, decimalparts
larger than three decimals are invalid input. I know floating point
numbers are not represented exactly in computers so this is tricky
business. This seems to work on my laptop, it's to be used by students
in an assignment to write a monetary class so it mustn't be perfect,
Wrong approach. Monetary amounts are integers, just with a weird I/O
format.
HTH,
Michiel Salters.
"Greg" <gr****@pacbell .netwrote in message
news:11******** **************@ f16g2000cwb.goo glegroups.com.. .
: Markus Svilans wrote:
: Hi Eric,
: >
: This function does what you want:
: >
: #include <cmath>
: >
: void split_double(do uble d, int precision,
: int &integer_par t, int &fractional_par t)
: {
: integer_part = (int)d;
: fractional_part = (int)( (d - integer_part) * std::pow(10,
: precision) + 0.5);
: }
: >
: >
: The +0.5 in the integer cast is to achieve proper rounding. For
: example, if precision is 3, then 0.4567 will round to 0.457 instead
of
: 0.456.
Please see what happens with d=5.999 and precision=2:
integer_part = 5;
fractional_part = 100;
I don't think that this would be acceptable to the OP.
: There are several rounding behaviors possible (round toward nearest,
: round toward zero, round away from zero and so forth). The rounding
: behavior that happens to be the "proper" one depends on the
: application. And in this case, if the proper behavior to round to the
: nearest three-digit decimal fractional representation, then adding 0.5
: will not work for all values: for example -0.4567 will round to -0.456
: even though -0.467 is closer in value.
:
: A program can readily divide a double into integer and one-thousandth
: units (rounding toward nearest represention) like so:
:
: #include <math.h>
:
: // d is the double
: int integerUnits = d; // truncate
:
: int fractionalUnits = fmod( round(d * 1000.0), 1000.0);
Unfortunately, this doesn't work any better.
Starting with d=5.99999999, you will end up with:
integer_part = 5;
fractional_part = 0;
Neither do the subsequent proposals address the above problem.
One should first round the whole number, then proceed with
the decomposition.
One could use something like:
long long modulus = round( abs(d*1000) );
long integerUnits = modulus / 1000;
long fractionalUnits = modulus % 1000;
// ... then handle the sign as desired if d<0
But what do you want to do with the result?
If it is for display purposes, pass the double value directly
to a printing function from the standard (C or C++) library.
If it is for computation purposes, why not use fixed-point
integer arithmetic in the first place, as Michael pointed out ?
Ivan
-- http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: jose luis fernandez diaz |
last post by:
Hi,
My OS is:
cronos:jdiaz:tmp>uname -a
HP-UX cronos B.11.11 U 9000/800 820960681 unlimited-user license
I compile in 64-bits mode the program below:
|
by: Fred Ma |
last post by:
I'm using the expression "int a = ceil( SomeDouble )".
The man page says that ceil returns the smallest
integer that is not less than SomeDouble, represented
as a double. However, my understanding is that a
double has nonuniform precision throughout its value
range. Will a double always be able to exactly
represent any value of type int? Could someone please
point me to an explanation of how this is ensured,
given that the details of...
|
by: John Salerno |
last post by:
This is an example in the book I'm reading:
string fullName = " Edward C Koop ";
fullName = fullName.Trim();
string names = fullName.Split(' ');
string firstName = names; // Edward
Two questions about this:
1. Why do you use single quotes with Split() instead of double? Is this
|
by: cj |
last post by:
VB2003. I need a large positive integer. Which is larger int64 or double?
I see int64 also apparently is known as long and will hold
-9,223,372,036,854,775,808 through 9,223,372,036,854,775,807.
But I'm not good with the E+??? notation so when I'm told double holds
-1.79769313486231570E+308 through
-4.94065645841246544E-324 for negative values; 4.94065645841246544E-324
through 1.79769313486231570E+308 for positive values.
|
by: Bo Peng |
last post by:
Dear C++ experts,
I need to store and retrieve a meta information that can be int or
double. The program would be significantly simpler if I can handle two
types uniformly. Right now, I am using a single interface:
void setInfo(double); // store info
double info(); // retrieve info
and use
| |
by: Pascal |
last post by:
hello and soory for my english
here is the query :"how to split a string in a random way"
I try my first shot in vb 2005 express and would like to split a number in
several pieces in a random way without success.
for example if the number is 123 456 : i would like to have some random
strings like theese :
(12 * 10 000) + (345 * 10) + (6*1)
or
(123*1 000)+(4*100)+(5*10)+(6*1)
etc...
|
by: Johs |
last post by:
I have:
int a = 1;
int b = 2;
double c = a/b;
Is it somehow possible to divide these two integers and get the result
as a double 0.5? Or do they both have to be declared as doubles?
|
by: Alexander Stoyakin |
last post by:
Hello,
please advise on the following issue. I need to check that difference
between two double values is not higher than defined limit.
int main()
{
double limit = 0.3;
double val1 = 0.5, val2 = 0.2;
if ( (val1 - val2) limit )
|
by: Bill Reid |
last post by:
I just noticed that my "improved" version of sscanf() doesn't assign
floating point numbers properly if the variable assigned to is declared
as a "float" rather than a "double". (This never cropped up before, since
I rarely use "float"s for anything, and hardly ever use the function for
floating-point numbers in the first place; I just was messing around
testing it for all cases and noticed a problem.)
Anyway, it is declared and I...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
| |
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth.
The Art of Business Website Design
Your website is...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert into image.
Globals.ThisAddIn.Application.ActiveDocument.Select();...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
|
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...
| |