BookmarkSubscribeRSS Feed
ling0152
Calcite | Level 5

Hello everyone,

I’m encountering an unexpected rounding behavior when applying the TIME12.3 format to numeric values that share the same decimal part.

For example, consider the values 99.3765 and 67.3765. After applying TIME12.3, I obtain different results:

  • 99.3765 → 0:01:39.377

  • 67.3765 → 0:01:07.376

This suggests that 99.3765 is being rounded up to .377, while 67.3765 is not.

Suspecting a floating-point representation issue, I examined their binary64 representations and converted them back to decimal. The results are:

 

  • For 99.3765
    TIME12.3 result: 0:01:39.377
    Binary64: 0100000001011000110110000001100010010011011101001011110001101010
    Converted back: 99.37649999999999295142

 

  • For 67.3765
    TIME12.3 result: 0:01:07.376
    Binary64: 0100000001010000110110000001100010010011011101001011110001101010
    Converted back: 67.37649999999999295142

 

Both values are stored slightly below 0.3765, so based purely on their numeric representations, neither appears to meet the usual rounding threshold for .377. However, SAS rounds up 99.3765 but not 67.3765.

 

Does anyone know why TIME12.3 would produce different rounding behavior for these two values? Could this be related to how SAS internally decomposes time values (for example, hours, minutes, seconds) or applies rounding during formatting?

For reference, here is the code I used:

data num;
input value;
datalines;
99.3765
67.3765
;
run;

data time;
set num;
time = put(value, time12.3);
b64 = put(value, binary64.);
run;

Any insight into SAS’s internal rounding logic for time formats would be greatly appreciated.

 

4 REPLIES 4
yabwon
Amethyst | Level 16

Interesting observation is that up to 100 minutes the rounding changes several times:

data num;
  do i=0 to 1e6;
    value=i+0.3765;
    output;
  end;
  format value 12.5;
run;

data time;
  set num;
  time = put(value, time12.3);

  r=scan(time,-1,"."); /* group by rounding */
run;

data time2;
  set time;
  by r notsorted;

  if first.r or last.r then output; /* get start and end of every group */
run;

Printout:

yabwon_0-1767167112542.png

 

The higher number of seconds the "longer" the group.

 

Bart

 

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



ling0152
Calcite | Level 5

Hi Bart,

 

Thanks for your input, this is a very interesting experiment. It appears that the flip points occur at powers of two and near minute/second boundaries (e.g., 120, 180, 240). It seems that the internal rounding behavior may be related to the binary64 representation of the data and how SAS handles minute/second carry-over internally. 

ballardw
Super User

There a several places that decimal conversions can act oddly. If you see one then it may be that you should round to a desired decimal level before applying an inconsistent format.

ling0152
Calcite | Level 5

Thanks for your input! I agree that the best practice is to use round() to control the decimal precision before applying a TIMEw.d format. I was mainly curious about the underlying logic and implementation details that lead to these edge-case behaviors.

sas-innovate-2026-white.png



April 27 – 30 | Gaylord Texan | Grapevine, Texas

Registration is open

Walk in ready to learn. Walk out ready to deliver. This is the data and AI conference you can't afford to miss.
Register now and lock in 2025 pricing—just $495!

Register now

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 4 replies
  • 143 views
  • 2 likes
  • 3 in conversation