-4

I need to round some numbers stored as floating points.

Values are like: 0.000000123, which for example represents 123ns

I need to extract the 123 (so that can be expressed in ns) and round it to the next "ten".

So, for example I want to exctract: 130e-9

Do you have any suggestion?

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
JoJo
  • 39
  • 3
  • 2
    You are aware that 0.000000123 is not an exact floating point value (under IEEE754)? – Bathsheba Jul 18 '17 at 12:44
  • I don't get what you mean... – JoJo Jul 18 '17 at 12:45
  • so 123 rounds to 130 is what you are saying? so when you talk about tens places the 2 is not tens place, so you have already multiplied by 1000000000 and then you want to round to the nearest ten? – old_timer Jul 18 '17 at 12:45
  • Another discussion on _[displaying scientific notation in C](https://stackoverflow.com/questions/21287974/why-is-printf-not-using-scientific-notation)_ – ryyker Jul 18 '17 at 12:45
  • you are using base 10 numbers and asking a floating point computer (base 2) question. many base 10 numbers cannot be represented exactly in floating point, that is what Bathsheba is saying – old_timer Jul 18 '17 at 12:46
  • @old_timer yes, that's what I'm saying. I know I can multiply it, but it is not completley general. what if the number is ms? You're right, I din't specify that I dont know if it is ms, ns, ps... a priori – JoJo Jul 18 '17 at 12:51
  • so you are applying some sort of engineering notation to this? what is special about 10-3 vs 10-4? and then rounding to "ten" after that? you are basically picking an arbitrary, BASE 10, power of the base and asking if the fraction to the right of that after moving the decimal point is exactly zero? but dont understand that this is a base 2 system? equals comparisons on floating point are not wise. but on fixed point work just fine. – old_timer Jul 18 '17 at 12:56
  • I assume this is a homework question? – old_timer Jul 18 '17 at 12:56
  • Maybe this: `double d = 0.000000123; double extractedvalue = round(d * 100000000 + 1) * 10;`. But your question is a bit unclear. – Jabberwocky Jul 18 '17 at 12:57
  • In base 2 if you wanted to say align on a four byte boundary you would do x=(x+3)&(~3). The same works here but base 10...You can do it in the form of a test rather than the AND... – old_timer Jul 18 '17 at 12:58
  • Just to help me understand the question, you want to round up to the next multiple of ten nanoseconds, then print in expontential representatoin? I think that the example value would be represented as 1.3e-7, or even 0.13e-6. What representation result do you want for 2564ns? – Yunnosch Jul 18 '17 at 13:17
  • Posting more examples of input and expected output would add clarity. Like t = 123e-9, 123.4999e-9, 0, 1.0e-90, 10e11, 123.000000000001e-9, 123.999999999999e-9, -123e-9 --> what results should occur? – chux - Reinstate Monica Jul 18 '17 at 14:42

2 Answers2

1

If concerns about the floating points such as came in the comment can be ignored the idea is multiply the given number up to it is greater than one. Then get the other numbers after the point by multiplying in 100 and then proceed as you want.

 double a; // is given a non-zero for example 0.0000000123...
 double num = a;
 while(num < 1.)
 {
      num *= 10;
 } // at the end of the while 1.23...
 num *= 10; //12.3...
 int result = ((int)num)*10 + 10; // 130

the result is what you want. Its unit depends on the context.

However, it have some errors in computation level. As you know, computation is taken place in base 2 and all of these computations in base 10 can have some computational errors in base 2. To find this you can follow this issue. Hence, you can see this code just in an algorithmic view.

OmG
  • 18,337
  • 10
  • 57
  • 90
1

There are several ways to do rounding, but it sounds like you're looking to round up (round towards +infinity), which is also called the ceil.

Since you have units of seconds and you want to get units of 10ns you need to divide by 10ns (1e-8, which is the same as multiplying by 1e8) then use the ceil function. For instance

double val = 123e-9;
int val10ns = ceil(val*1e8);

(this assumes that you have c99 ceil available, if not see here for an implementation)

Then if you want to output this as a string, you just need to convert 'val10ns' and append "0ns", like this

printf("val in units of 10ns: %d0ns\n", val10ns);

Lastly, you might want to do something to handle small values. For instance, 1e-90 seconds will still round up to 10ns. For instance you could first do a round to zero to get units of ns and then do a ceil to get units of 10ns.

Paul Floyd
  • 5,530
  • 5
  • 29
  • 43
  • This is a good answer for OP - (aside from `int val10ns`. I'd used `double val10ns`) I do not see a reason for the DV. – chux - Reinstate Monica Jul 18 '17 at 14:21
  • 1
    I agree - a double for the rounded result would be fine as well, especially since a double can represent all possible values of an int without loss of information. – Paul Floyd Jul 18 '17 at 14:34