0
int digit = 1;
float result=0.0;
double temp = 200000;
float tick = 0.00100000005;

result = digit/1000000.0;
long long phase = temp*result*1000/tick*1000

result will be equal to 9.99999997e-07. If manually calculate it should be 0.000001 How can I make the exponential num to be 0.000001? Thanks.

if result = 9.99999997e-07 phase calculated will be 199999,however if result = 0.000001 phase calculated will be 200000. So my problem is result.

Add in

Jaden Ng
  • 141
  • 1
  • 12
  • holy implicit casts, Batman! – RobP Apr 08 '14 at 06:02
  • Some light reading : [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html). – WhozCraig Apr 08 '14 at 06:06
  • @n.m. after read the How To Represent 0.1 In Floating Point Arithmetic And Decimal .I still cant figure out how to solve my problem.Could you help? – Jaden Ng Apr 08 '14 at 07:02
  • Phase is usually a real number. If you for some inexplicable reason need your phase variable to be of an integral type, and you need to convert it from floating point, consider proper rounding. Read stuff linked in the comments too – n. m. could be an AI Apr 08 '14 at 09:29

2 Answers2

2

For finance and certain other uses, the easiest way is to work in multiples of your smallest unit... in your example, it might be "microns":

inline long long units_to_microns(long long units) { return units * 1000000; }
long long digit = units_to_microns(1);
long long result = digit / 1000000;

Then write some custom code to print numbers a decimal point where you want it:

std::string microns_to_string(long long microns)
{
    std::ostringstream oss;
    oss << microns / 1000000;
    if (microns % 1000000)
        oss << '.' << std::setfill('0') << std::setw(6) << microns;
    return oss.str();
}

A more structured (and reliable) way to do this is offered by the boost Units library. That way, you can specify the units of specific variables, and if e.g. one was in metres and another kilometres, you could add them without any special care.

If you're dealing with irrational numbers and rounding them off to a specific precision early on is not useful, then you're best off either using double (for some more significant digits of precision), or a custom library like GMP - the GNU Multiple Precision Arithmetic Library.

BTW - What Every Computer Scientist Should Know About Floating-Point Arithmetic is commonly recommended reading in this space.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Isn't it result will be equal to 1 if perform units*1000000 then divide 1000000 again? – Jaden Ng Apr 08 '14 at 06:50
  • 1
    @JadenNg: yes - that's the point - you don't lose any precision, as the result is exactly 1. With floats, 1/1000000.0*1000000.0 might equal e.g. 0.999999997. – Tony Delroy Apr 08 '14 at 07:25
  • Understand now.Thanks very much. – Jaden Ng Apr 08 '14 at 07:32
  • Btw I still cannot get the result ot be 0.000001.Could you guide me.Coz 1/1000000 should be 0.000001 if calculated manually. – Jaden Ng Apr 08 '14 at 08:03
  • @JadenNg: I will need to know a bit more first - what does your code look like? How are you reading / using / outputting the values? What calculations are you doing with them? – Tony Delroy Apr 08 '14 at 08:05
  • My code is almost look like the above code.Just i need to use result to put in to another algorithm phase = result*A/B in this case my phase always cant get the exact expected result coz my result = 0.99999997 but if result = 0.000001.then phase will be calculated correctly which match my expected result. – Jaden Ng Apr 08 '14 at 08:08
  • result is equal to 9.99999997e-07 not 0.99999997 – Jaden Ng Apr 08 '14 at 08:10
  • I am using eclipse to debug so when i read the value i just hover to read. – Jaden Ng Apr 08 '14 at 08:11
  • The thing is, if the "[an]other algorithm phase" works with `float` input, then it's just not possible to give it input of exactly 0.000001 - that's not a value that any `float` can store. Floats are basically a sum of `(a/2 + b/4 + c/8 + d/16...) * 10^n`, where each of `a`, `b` etc are 0 or 1, but there's a small finite number of such fractions contributing so you don't get many significant digits. If the other algorithm needs to be more precise, it has to accept and use a higher precision numeric data type than `float` (like `double` or an integral number of microns). – Tony Delroy Apr 08 '14 at 08:18
  • Hi i just edited my 1st post and explain in more detail.Maybe you can understand clearly. – Jaden Ng Apr 08 '14 at 08:25
  • You might find this helpful: if you type 0.000001 in the "Decimal Representation" field of [online calculator](http://www.h-schmidt.net/FloatConverter/IEEE754.html), it reports a "cast to double" value of ~9.999999974752427e-7 - that's closer to the actual value the `float` could store. If you click the last two checkboxes it will repreent the next larger number a `float` can store: that's ~1.0000001111620804e-6. Basically, a `float` cannot store anything between these two numbers: it has to be either a bit too small or a bit too large. – Tony Delroy Apr 08 '14 at 08:28
  • For your updated code, if you had perfect precision it basically ends up being `0.2/0.00100000005`... the mathematically precise result is (considerably) < 200, so the conversion to integer correctly truncates downwards to 199 (such conversions never round to the nearest value, they always truncate; to round, you must adjust the floating pointer value before conversion to integer). – Tony Delroy Apr 08 '14 at 09:01
0

You can't, because the number 1/1000000.0 cannot be represented exactly in binary. You can improve the accuracy by using a double. This type of question is pretty common here. I've found this link to be helpful:

https://docs.python.org/2/tutorial/floatingpoint.html

(it's for Python, but the issues are the same).

James King
  • 6,229
  • 3
  • 25
  • 40